如何编写接受包含整数和标点字符的用户输入的C程序?

#include  #include  int main() { char value[50]; char *end; int sum = 0; long conv; while(conv != 0 ) { printf("Enter a measurement and unit(Ex: 4' or 3\";0' or 0\" when done): "); fgets(value, 50, stdin); conv = strtol(value, &end, 10); if(strstr(value, "\'") != NULL) { conv = strtol(value, &end, 10); sum = sum + (conv*12); } else if(strstr(value, "\"") != NULL) { conv = strtol(value, &end, 10); sum = sum + conv; } } printf("Total: %d, %s\n", sum, "inches" ); return 0; } 

更新仍然有新程序的问题..确保从这里去哪里。 它接受数字和引号,但是当我输入单引号来指定英尺时,它应该只输入我输入的任何数字12。 UPDATE2以下是我们在编写C程序时应该记住的Assembly函数:

 void printStr(char *) Arguments: edi = address of null-terminated string to print Returns: Nothing void printUInt(unsigned) Arguments: edi = Unsigned integer to print Returns: Nothing char getchar() Arguments: None Returns: eax = the next character uinsigned readUInt() Arguments: None Returns: eax = an unsigned int read from stdin. (eax is 0 on error) 

我必须编写一个C程序,提示用户输入一个测量(数字)和单位(’或’,代表英尺或英寸),然后在用户输入’0’长度后打印出以英寸为单位的总长度。充当哨兵价值。

这个程序只需要我作为一种方式来构建具有类似结构的汇编程序。 问题是,它必须围绕4个函数构建,这些函数将被调用以帮助执行某些操作。

所以我的C程序应该与这些function类似地构建。 这就是我所拥有的:

这是我的计划:

更新:

 int main() { char value[50]; char *end; int sum = 0; long conv; while(conv != 0) { printf("Enter a measurement and unit: "); fgets(value, 50, stdin); conv = strtol(value, &end, 10); if(value[1]='\'') { sum = sum + (conv*12); } if(value[1]='\"') { sum = sum + conv; } } printf("Total: %d\n", sum); return 0; } 

旧:

 int main() { int sum = 0; int value; char symbol; while(value != 1) { printf("Enter measurement and unit: "); scanf("%d,%d", &value, &symbol); if(symbol == "'") { sum = sum + value*12; } else if(symbol == ''' ) { sum = sum + value; } sum = sum + value; } printf("Total: %d", sum); return 0; } 

我希望我有足够的信息可以帮助我,即使我知道我们暂时缺少完整的function。 而且我知道IA32汇编转换不是我的主要问题,如果我遇到问题,我想我会把它保存到另一个,但我希望这个高级语言程序得到纠正会让我朝着正确的方向前进。 提前致谢!

使用%c而非%d获取角色。 将行更改为这样。

 if ( scanf("%d,%c", &value, &symbol) != 2 ) continue; 

比较你必须这样做,

 if(symbol == '\"') { sum = sum + value*12; } else if(symbol == '\'' ) { sum = sum + value; } 

此后输出,

 Enter measurement and unit: 2," Enter measurement and unit: 3,' Enter measurement and unit: 1," Total: 45 

当您考虑编写将转换为汇编的程序时,您希望将自己限制为使用与汇编中可用的系统调用具有1对1关联的调用。 这意味着离开缓冲输入/输出的高级世界并使用无缓冲的低级输入/输出方法,您负责计算进出程序的每个字节。 即使是用C语言进行read的低级例程,也提供了一些在汇编时必须手动处理的function。

为了提供这种低级I / O的合理示例,我写了一个简短的例子,以英尺或英寸为单位进行输入测量,并保持输入的英尺和英寸的总计。 该代码还将12英寸以上的任何英寸转换为英尺。 这个例子提供了一个很好的近似方法,你将在程序集中做同样的事情。 花点时间了解每个部分的作用,如果您有疑问,请告诉我。 您编写的低级代码,完成看似简单的任务所需的时间越长。 你的assembly可能会长3倍。

该程序需要输入表格numfeet'numinches" 。所以输入10英尺,输入10' ,输入10"英寸,输入10"

 #include  #include  #define STDINFD 0 #define STDOUTFD 1 #define newline write (STDOUTFD, "\n", 1) #define MAXS 32 int main (void) { ssize_t n = 0; /* number of characters read */ size_t i = 0; /* general iteration variable */ size_t digits = 0; /* digit counter */ char buf[MAXS] = {0}; /* buffer to hold input */ char *bp = buf; /* pointer to input buffer */ char length[MAXS] = {0}; /* buffer to hold measurement */ char *p = length; /* pointer to measurement */ char fbuf[MAXS] = {0}; /* buffer to hold feet */ char *fp = fbuf; /* pointer to feet */ char ibuf[MAXS] = {0}; /* buffer to hold inches */ char *ip = ibuf; /* pointer to inches */ unsigned feet = 0; /* total feet entered */ unsigned inches = 0; /* total inches entered */ unsigned num = 0; /* general unsigned value */ unsigned mlt = 1; /* place multiplier value */ unsigned incvt = 0; /* inches to feet conversion */ char unit = 0; /* buffer for ''' or '"' */ char const digit[] = "0123456789"; /* conversion string */ /* input prompt and labels */ char prompt[] = "\n Enter measurement with units [feet' or inches\"]: "; char nlabel[] = "\n number : "; char ulabel[] = "\n unit : "; char flabel[] = "\n feet : "; char ilabel[] = "\n inches : "; /* write prompt to stdout */ write (STDOUTFD, prompt, sizeof prompt); /* read length and unit until [CTRL+D] entered */ while ((n = read (STDINFD, bp, 32)) != 0) { /* re-initialize values for each loop */ bp = buf; p = length; fp = fbuf; ip = ibuf; i = 0; num = 0; incvt = 0; mlt = 1; unit = 0; /* parse each character read into buf */ while (bp[i] != '\n') { if (bp[i] >= '0' && bp[i] <= '9') /* is a digit */ *p++ = bp[i]; if (bp[i] == 0x27) /* is a ' */ unit = bp[i]; if (bp[i] == '"') /* is a " */ unit = bp[i]; i++; } /* null-terminate / decrement length pointer */ *p = 0; p--; /* write length and unit to stdout */ write (STDOUTFD, nlabel, sizeof nlabel); write (STDOUTFD, length, p - length + 1); write (STDOUTFD, ulabel, sizeof ulabel); write (STDOUTFD, &unit, sizeof unit); newline; /* convert characters in length to number */ for (i = p - length; p >= length; p--) { num += (*p - '0') * mlt; mlt *= 10; } /* test unit and add to feet or inches */ if (unit == '"') inches += num; if (unit == 0x27) feet += num; /* convert inches > 12 to feet */ if (inches > 12) { incvt = inches / 12; inches -= incvt * 12; feet += incvt; } /* write label for total feet to stdout */ write (STDOUTFD, flabel, sizeof flabel); /* determine number of digits in feet */ i = 1; digits = 0; while (feet >= i && (1UL << 32)) { digits++; i *= 10; } /* convert number to characters in feet buffer */ num = feet; fp += digits - 1; while (fp >= fbuf) { *fp-- = digit [num % 10]; num /= 10; } /* write the number of feet and label for inches to stdout */ write (STDOUTFD, fbuf, digits); write (STDOUTFD, ilabel, sizeof flabel); /* determine number of digits in inches */ i = 1; digits = 0; while (inches >= i && (1UL << 32)) { digits++; i *= 10; } /* convert number to characters in inches buffer */ num = inches; ip += digits - 1; while (ip >= ibuf) { *ip-- = digit [num % 10]; num /= 10; } /* write the number of inches and newline to stdout */ write (STDOUTFD, ibuf, digits); newline; /* zero all buffers */ for (i = 0; i < MAXS; i++) buf[i] = length[i] = fbuf[i] = ibuf[i] = 0; /* prompt for next input ([CTRL+D] to quit) */ write (STDOUTFD, prompt, sizeof prompt); } newline; return 0; } 

示例/输出

 $ ./bin/read_measurement Enter measurement with units [feet' or inches"]: 10" number : 10 unit : " feet : inches : 10 Enter measurement with units [feet' or inches"]: 10' number : 10 unit : ' feet : 10 inches : 10 Enter measurement with units [feet' or inches"]: 4" number : 4 unit : " feet : 11 inches : 2 Enter measurement with units [feet' or inches"]: 

更新您的高级代码

如果您要继续使用高级函数,请在调用strtol之后使用end已指向该数字后面的下一个字符的事实。 例如:

 while (printf ("\nEnter a measurement and unit: ") && fgets (value, 50 - 1, stdin)) { errno = 0; conv = strtol (value, &end, 10); if (errno == 0 && value != end) { if (*end == '\'') sum = sum + (conv*12); else if (*end == '\"') sum = sum + conv; else printf ("error: no unit following number.\n"); } else printf ("error: no value read.\n"); } 

我在你的“更新”代码中看到了几个错误:几乎每一行都有一个错误。

 int main() 

标头文件丢失。 (如果你给我们一个完整的程序,可以编译和测试而不需要修改,我们就会更容易帮助你。)

应该是int main(void) ; 空的参数括号是穷人的风格。

 { char value[50]; char *end; int sum = 0; 

这可以。

  long conv; while(conv != 0) 

使用未初始化的变量。 我会写一个do-while循环代替。

  { printf("Enter a measurement and unit: "); 

不必要地使用printf (更好的fputs因为不需要格式化)。

  fgets(value, 50, stdin); 

如果你有getline ,请使用它。

  conv = strtol(value, &end, 10); 

在使用strto*函数之前,必须手动将errno为零,因为某些错误只能以这种方式显示。

  if(value[1]='\'') 

你眼前的问题就在这里。 这一行有三个错误:

  • 您尚未检查strtol是否返回错误。
  • value[1]fgets读取第二个字符 ,而不是紧跟在数字后面的字符。 数字后面的字符end[0]
  • 比较用途== ,不是= ; 这个条件是为value[1] 赋值 '\'' ,然后测试'\''是否为非零值; 因为'\''必须非零,if语句的主体总是执行,这就是为什么你看到它总是乘以12.如果你在=周围放置空格,这将更加明显。 如果您在启用了警告的情况下运行了编译器,它就会告诉您这个错误。
  { sum = sum + (conv*12); } 

  if(value[1]='\"') 

与早期的if statement相同的问题; 如果是,应该是。

  { sum = sum + conv; } 

由于字母后面的字符既不是'也不是"因此在此处缺少您报告错误的else条款。

在编号和单位指定符后缺少对垃圾输入的检查。

  } printf("Total: %d\n", sum); return 0; } 

其余的都没问题


您可能还可以使用入门来了解如何检查strtol是否返回错误。 这有点挑剔,因为strtol没有特殊的返回值表示错误; 如果发生错误,它将设置errno ,或者不消耗任何字符 。 不幸的是,当一个错误没有发生时,它不一定清除errno ,所以你必须自己做:

 errno = 0; conv = strtol(value, &end, 0); if (end == value || errno) { fputs("Invalid number, or no number entered\n", stderr); continue; }