如何使用scanf工作?

时间:2013-06-14 14:49:39

标签: c scanf gets

使用gets模仿scanf的功能的最佳方法是什么?

这是我目前的尝试

 int main()
 {
    char cvalue[20];   //char array to store input string
    int iloop=0;      //integer variable for loop

    for(iloop=0;iloop<20;iloop++)     // for loop to get the string char by char
    {
        scanf("%c",&cvalue[iloop]); //getting input
        if(cvalue[iloop]=='\n')    //if input is newline skip further looping
        break;
    }                    // end of loop

    cvalue[iloop]='\0';         //set end of the character for given input
    printf("%s",cvalue);        //printing the given string
    return 0;
}

3 个答案:

答案 0 :(得分:2)

您可以scanf这种方式使用gets

scanf("%[^\n]",&a);

答案 1 :(得分:0)

您的尝试并不真正模仿gets(),因为gets()只是将字节放入提供的缓冲区,直到到达行尾。你应该意识到gets()是危险的,应该避免。它不提供缓冲区溢出的任何保护。因此,模仿它也是值得怀疑的。

鉴于此,你的尝试有一些我看到的缺陷。首先,它循环到输入缓冲区的完整大小。如果输入行是20字节或更长,这不会给你留下存储NUL终结符的空间。这意味着您可以尝试将\0存储在数组边界外的cvalue[20]。您可以通过缩短for循环来解决此问题:

    for(iloop=0;iloop<19;iloop++)     // for loop to get the string char by char

第二个缺陷是您不检查scanf()调用是否成功。如果您检测到故障,您还应该离开循环:

        if (scanf("%c",&cvalue[iloop]) != 1) { //getting input
            break;
        }

以下是我尝试使用gets()创建更安全的scanf()版本。

char *getsn (char *s, size_t sz) {
    char c;
    char fmt[sizeof(sz) * CHAR_BIT + sizeof("[^\n]")];
    if (sz == 0) return 0;
    if (sz == 1) {
        s[0] = '\0';
        return s;
    }
    s[sz-2] = '\0';
    snprintf(fmt, sizeof(fmt), "%%%lu%s", (unsigned long)sz-1, "[^\n]");
    switch (scanf(fmt, s)) {
    case 0:  s[0] = '\0';
             scanf("%c", &c);
             return s;
    case 1:  scanf("%c", &c);
             if (s[sz-2] != '\0' && c != '\n') {
                 ungetc(c, stdin);
             }
             return s;
    default: break;
    }
    return 0;
}

更安全的版本使用snprintf()创建一个格式字符串,用于限制scanf()应存储的字符数。因此,如果提供的sz参数为100,则生成的格式字符串将为"%99[^\n]"。然后,它确保仅从输入流中删除\n(如果实际遇到它)。

答案 2 :(得分:0)

您需要观察gets()的常见危险。

使用scanf()的挑战是 1)确保消耗\nscanf("%[^\n]",...不这样做。
2)如果仅读取str,则确保\0获得\n 3)处理EOF和I / O错误并返回0 4)确保前导空格被str读入,scanf("%s"跳过它们。

#include <stdio.h>
// On success, the gets() returns str.
// If EOF encountered, the eof indicator is set (feof).
// If this happens before any characters could be read, 
//    pointer returned is a null pointer.
//  If a read error occurs, the error (ferror) is set
//    and a null pointer is also returned.
char *gets_via_scanf( char * str ) {
  // Reads characters from stdin & saves them into str until \n or the end-of-file.
  // \n, if found, is not copied into str.
  int retval = scanf("%[^\n]",str);  // %[ does not skip leading whitespace
  if (retval == EOF) return 0;
  if (retval == 0) {
    *str = '\0';  // Happens when users only types in \n
  }
  char ch;
  scanf("%c",&ch); // Consume leftover \n, could be done with getc()
  return str;
}