C中的重定向输入:fgets()行结尾“\ n”干扰strcmp()

时间:2014-03-09 15:54:08

标签: c string fgets strtok

这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int individualAverage(int data[][20],int j)
{
    int k,average=0;
    for(k=0;k<10;k++)
    {
        average += data[k][j];
    }
    return average;
}

int main()
{
    int var,indAvg=0;
    int i=0,j,k;
    char *experiments[20];
    int data[10][20];
    char str[100],str2[100];
    char *ptr, *token;
    int no_line=1;


    while(fgets(str,100,stdin) != NULL && (strcmp(str,"*** END ***") && strcmp(str,"*** END ***\n")))
    {
        if(no_line % 2 == 0)
        {
            k=0;
            token = strtok (str," ");
            while (token != NULL)
            {
                sscanf (token, "%d", &var);
                data[k++][i] = var;
                token = strtok (NULL," ");
            }
            i++;
        }
        else
        {
            ptr = strdup(str);
            experiments[i] = ptr;
        }
        no_line++;
    }

    fgets(str,100,stdin);
    token = strtok(str," ");
    while(token != NULL && (strcmp(token,"4") && strcmp(token,"4")))
    {
        sscanf (token, "%d", &var);
        printf("DATA SET ANALYSIS\n1.\tShow all the data\n2.\tCalculate the average for an experiment\n3.\tCalculate the average across all experiments\n4.\tQuit\nSelection: %d\n\n",var);
        switch(var)
        {
        case 1 :
            for(j=0;j<i;j++)
            {
                printf("%s",experiments[j]);
                for(k=0;k<10;k++)
                {
                    printf("%d ",data[k][j]);
                }
                printf("\n");
            }
            printf("\n");
            break;
        case 2 :
            printf("What experiment would you like to use?\n");
            token = strtok (NULL," ");
            sscanf (token, "%s", &str);
            for(j=0;j<i;j++)
            {
                if(strcmp(experiments[j],str) == 0)
                {
                    indAvg = individualAverage(data,j); 
                    printf("Experiment: %s",experiments[j]);
                    printf("The individual average of the experiment is %d\n",indAvg);
                    break;
                }
            }
        }
        token = strtok(NULL," ");
    }
}

好的,所以我有一个方法,需要重定向输入行。这些线成对出现。第一行是实验的名称,第二行具有由该实验的空格分隔的10个值。在这些对之后,有一个结束行"*** END ***"

在此行之后,最后一行包含有关如何处理数据的说明。

我目前遇到的问题是我使用fgets()将第一对行的字符串存储到我声明为char *experiments[20];

的变量中

由于'\n'

,此数组指向的每个字符串在字符串末尾都会显示fgets()

回到最后一行说明。你有1-4的价值。现在我正在看指令2.它告诉实验的平均值。所以在最后一行的2之后,必须有一个实验的名称。我用过:

char str[100];
int var;
char *token;
token = strtok(str, " ");
sscanf (token, "%d", &var);

将该行的第一个值转换为var(假装为2)。所以在那之后将是一个字符串。说它是Test 1,我会用

token = strtok (NULL," ");
sscanf (token, "%s", &str);

将值转换为str,然后我将其与experiments进行比较以获取所有可能的索引。
但是,因为fgets()在行的末尾给出了'\n',所有实验字符串最后会有'\n',而str只会有实验的名称没有'\n'因此,即使'\n'是字符串之间的唯一区别,它们也永远不会相等。

任何解决方案?

2 个答案:

答案 0 :(得分:4)

由于您知道字符串末尾可能有\n,因此您可以检查它,如果它在那里则将其删除:

size_t len = strlen(str);
if (len != 0 && str[len-1] == '\n') {
    str[len-1] = '\0';
}

这会终止\n行,因此您的strcmp会成功。另一种方法是使用strncmp,并传递目标字符串的长度。但是,当\n的后缀更长时,这会产生误报的风险。

你也可以这样读取你的数据:

fscanf(f, "%99[^\n]", str);

答案 1 :(得分:1)

您可以制作自己的fgets版本,在遇到换行符时不会存储换行符,并将其称为myfgets。这样的事情会复制fgets的行为,我认为是根据description given in MSDN生成的:

char * myfgets( char * str, int n, FILE * stream ) {
    if ( n <= 0 ) return NULL;  // won't accept less than or equal to zero length

    int currentPos = 0;
    while ( n-- > 0 ) {
        int currentChar = fgetc( stream );
        if ( currentChar == EOF ) return NULL;
        if ( currentChar == '\n' ) break;
                    // if these two lines were in reversed order, 
                    // it would behave same as the original fgets
        str[currentPos++] = currentChar;
    }
    return str;
}

但当然另一种解决方案更简单,呵呵......