scanf数学表达式c

时间:2015-12-15 16:53:39

标签: c scanf

我是c语言学习的初学者,我有一个问题 我必须编写以下代码:用户输入数学表达式,例如2+3*7,代码应发送结果并考虑*/的优先级。

我想在第一步中将用户的表达式输入一个char数组(禁止使用字符串)。

int counter=0;
char test[50],input;

while (counter < 50 && scanf("%c", &input) != EOF ){
    test[counter] = input;
    counter++;
}

for (i = 0; i < counter; i++){
    printf("%c ", test[i]);
}

但是当用户输入时代码没有退出循环。怎么了?
我的第二个问题是,如果我不能使用字符串,那么将表达式输入char数组是个好主意吗? 我能用这种方式获得表达式的所有字符吗?

6 个答案:

答案 0 :(得分:1)

  

但是当用户输入时代码没有退出循环。

您的代码不会退出循环,直到获得EOF(这通常意味着用户按下Ctrl + D)或输入了50个字符,而不是输入。如果要在用户按Enter键时结束,则需要检查最后一个字符输入是否为换行符。

此外,如果您一次只读一个字符getchar可能比scanf更好。

读入一个char数组很好,只要你不能一次获得比缓冲区大小更多的字符,并确保你永远不会溢出缓冲区。

修改

如果要求你不能使用字符串只是意味着你不能使用string.h,那么表达式中就不允许使用空格了(所以&# 34; 4 + 5&#34;有效,但&#34; 4 + 5&#34;不是,你可以这样做:

char test[51],input;
scanf("%50s" &input);
printf("%s", input);

test中的额外字符用于空终止符。

答案 1 :(得分:1)

  

但是当用户输入时,代码没有退出循环。

如果你想在ENTER键之后断开循环,你必须在你的情况下检查:

while (counter < 50 && scanf("%c", &input) != EOF && input != '\n' ) {
...
}
  

我的第二个问题是输入表达式是否是个好主意   如果我不能使用字符串进入char数组?

是。没关系。 C字符串和char数组之间没有什么区别(例如终止NUL字节)。因此,如果您不能使用fgets(str, sizeof str, stdin);scanf("%s", buf);等字符串/行读取功能,那么您没有太多选择。

答案 2 :(得分:1)

您正在为scanf()测试EOF,这是对错误或文件结尾的测试,否则scanf()会返回与成功转换的格式字符串匹配的字段数。在这种情况下,当输入来自控制台时它不会失败,因为%c将匹配任何字符,如果没有字符存在,scanf()将无限期地在控制台上等待 - 您可以将EOF注入控制台输入,但在这种情况下似乎不太可能。

这里没有必要

scanf(),更简单的getchar()就足够了:

do
{
    input = getchar() ;
    test[counter] = input;
    counter++;

} while( counter < sizeof(test) && input != '\n' ) ;

请注意,与原始代码一样,这不会添加nul终结符(因此在这个意义上它不是“字符串”)。

由于对明显使用stdio的哪些部分有些不合理的限制:

do
{
    scanf( "%c", &input ) ;
    test[counter] = input;
    counter++;

} while( counter < sizeof(test) && input != '\n' ) ;

答案 3 :(得分:0)

你基本上需要写一个parser。您可以先拥有一些lexer(从字符流中提供令牌流)。然后,从一个标记流中,您的解析器将在内存中构建abstract syntax tree,或者它(在您的简单表达式中没有变量的表达式)在解析期间计算表达式。任何关于编译器的好书(例如dragon book)都会详细解释这一点。

有几种工具可用于生成解析器&amp;词法分析器。它们(夸张地)被称为compiler-compilers(但它们应该被称为解析器生成器)。 GNU bison就是这样一个工具。但您可以考虑ANTLR(可能是某些旧版本,ANTLR2或PCCTS)

您想要达到的目标是非常标准的练习。在bison的文档中给出了example (calc); recursive descent parser wikipage也有非常相似的代码。

具体关于scanf,请阅读scanf(3)&amp;的文档。 getchar(3)(以及ungetc ....)您可以使用getline(3)(或者甚至是终端上的readline(3))阅读整行(以便更轻松地解析它),或者fgets(3) ...

答案 4 :(得分:0)

  

但是当用户输入时代码没有退出循环。

输入'\n'是有效的char,可以使用scanf("%c", &input)阅读。只需阅读'2''+'即可。

  

我的第二个问题是,如果我不能使用字符串,是否最好将表达式输入char数组?

是的,这是合理的。代码需要1)不存储char超过数组大小2)跟踪数组中使用的元素。

  

我可以用这种方式获取表达式的所有字符吗?

如果您无法使用 stings ,也许您无法使用"%c"。使用fgetc(),fputc()

#define N 50
int counter=0;
char test[N];
int input;  // use int to distinguish EOF from a character.

while (counter < N && (input = fgetc(stdin)) != '\n' && input != EOF) {
  test[counter] = input;
  counter++;
}

for (i = 0; i < counter; i++){
  fputc(test[i], stdout);
}

答案 5 :(得分:0)

请注意,C本身没有string数据类型 ;在C中,字符串只是由0值字节(或多字节字符串的字节序列)终止的字符值序列。字符串存储作为char的数组,但不是char的每个数组都包含字符串。

如果您只是想从标准输入中获取一系列字符以进行进一步解析,这可能是最简单的方法:

char buffer[N]; // where N is large enough for one line's worth of input;
                // let's call it 80 for now.

while ( fgets( buffer, sizeof buffer, stdin ) )
{
  // process buffer
}

fgets会将标准输入流中的字符读取到buffer,直到它看到换行符(如果有空间,它将存储到buffer中)或读取{{1}字符。 sizeof buffer - 1将始终向缓冲区写入0字节以终止字符串。因此,例如,如果您的缓冲区大小为10个字符,并且您键入“2 + 3 * 4 Enter ”,那么fgets将包含buffer;没有足够的空间来存储换行符,但字符串是0终止的。

{'2', ' ', '+', ' ', '3', ' ', '*', ' ', '4', 0}如果无法从流中读取输入,则会返回fgets,因此上面的循环将一直运行,直到出现读取错误或直到NULL检测到EOF条件。

...然而

处理这种情况的常用方法是在输入和处理过程中一次读取一个字符;这样您就不必担心放置足够大的缓冲区来容纳整个表达式,只需要足够大的缓冲区来处理较大表达式(数字和运算符)中的标记