使用scanf读取特定单词

时间:2018-01-05 09:39:12

标签: c scanf

我试图查找文本中最常用的单词。在我的程序中,我输入了一些文字。单词和文本由" -----"(我需要在我的程序中搜索最常用的单词)分开。

但是,我发现当程序在文本中搜索单词时。它似乎无法用完循环(我在PC ^ 2上超出了时间限制)。然后,我发现问题来自这个函数(如果我注释这个函数我得到了错误的答案错误)。我是否误解了scanf的用法或错过了其他一些条件?

void inputTextTxt(void) {

  for (;;) {
   // toss all non-alpha-numerics
   scanf("%*[^a-zA-Z0-9_]");

   int cnt = scanf("%2047[a-zA-Z0-9_]", tmp);
   if (cnt != 1) {
     break; // or return
   }

   for (size_t i = 0; i < dic_actual_num; ++i) {
     if (strcmp(dicWord[i], tmp) == 0) {
       dicWcount[i]++;

     }
   }
  }
}
  • 不是数字,字母和&#39; _&#39;应该被视为空间
  • 每行的最长长度为1024

我的代码的其他部分

char tmp[2048];
char **dicWord;
int *dicWcount;
int dic_assume_num = 1, dic_actual_num = 0;

void inputDicTxt() {

    char divider[6] = "-----";
    dicWord = malloc( dic_assume_num * sizeof( char* ));

    for (;;) {

        scanf("%*[^a-zA-Z0-9_-]");
        int cnt_divider = scanf("%2047[-]", tmp);
        int cnt_alphaNumerics = scanf("%2047[a-zA-Z0-9_]", tmp);

        if (cnt_divider != 1 && cnt_alphaNumerics != 1)
            break;

        else if (cnt_divider) {
            if (strcmp(tmp, divider) >= 0) {
                dicWcount = calloc(dic_actual_num,  sizeof(*dicWcount));
                break;
            }
        }
        else if (cnt_alphaNumerics) {
            if (dic_actual_num >= dic_assume_num) {
                dic_assume_num *= 2;
                dicWord = realloc( dicWord, dic_assume_num * sizeof( char* ));
            }
            dicWord[dic_actual_num++] = strdup(tmp);
        }
    }
}


int main() {

    inputDicTxt();
    inputTextTxt();

    int mostNum = 0;

    for (int i = 0; i < dic_actual_num; ++i)
        if (dicWcount[i] > dicWcount[mostNum]) 
            mostNum = i;

    // print out the most frequent word and its number
    printf("%s %d\n", dicWord[mostNum], dicWcount[mostNum]);


    for (int i = 0; i < dic_actual_num; ++i)
        free(dicWord[i]);
    free(dicWord);
    free(dicWcount);

    return 0;
}
编辑:我在代码中已从while(feof(!stdin))更改为for(;;),但我仍然在判断系统上获得TLE

1 个答案:

答案 0 :(得分:0)

  

我是否误解了scanf的用法或错过了其他一些条件?

请务必查看Why is “while ( !feof (file) )” always wrong? @alk

然而在这种情况下,代码以可接受的功能方式使用while (!feof(stdin)) 几乎。所以这个问题可能在其他地方。 IAC,避免while (!feof(stdin))的弱点和通常的IO问题的磁性。

目前尚不清楚为什么OP的代码处于明显的无限循环中(除了罕见的输入错误或其他UB,如tmp太小) - 即使使用异常代码while (!feof(stdin)) {

下面是类似的代码,应该更干净地操作/调试。

OP以不稳定的方式使用while (!feof(stdin)),如果代码循环而不读取字符,则会导致无限循环。示例:输入错误。

而不是while (!feof(stdin)),检查保存数据的scanf()的返回值。不要像if (scanf("%2047[a-zA-Z0-9_]", tmp)那样简单地检查布尔值。检查它的价值。

void inputTextTxt(void) {
  for (;;) {
   // toss all non-alpha-numerics
   scanf("%*[^a-zA-Z0-9_]");

   char tmp[2048]; 
   int cnt = scanf("%2047[a-zA-Z0-9_]", tmp);
   if (cnt != 1) {
     break; // or return
   }
   for (size_t i = 0; i < dic_actual_num; ++i) {
     if (strcmp(dicWord[i], tmp) == 0) {
       dicWcount[i]++;
       // I'd expect a `break;` here as once a match is found, 
       // could another be found?   Why keep looking?
     }
   }
  }
}

迂腐地,像"%[a-z]"这样的扫描集范围并未普遍实现 - 它是实现定义的行为。高度可移植的代码需要"%[abcedfghijklmnopqrstuvwxyz]"。大多数系统都将"%[a-z]"理解为希望,所以我怀疑这是OP的问题。

从样式的角度来看,if (scanf("%2047[^a-zA-Z0-9_]", tmp)); else if具有误导性 - 它看起来像一个问题。如果代码仍然存在,请使用{;}清楚地划分它。

if (scanf("%2047[^a-zA-Z0-9_]", tmp)) {
  ;
} else if ...