【问题标题】:input string through scanf通过scanf输入字符串
【发布时间】:2009-04-23 14:57:59
【问题描述】:

我想问有没有办法通过scanf在字符串中输入空白, 我正在使用这个 [^\n] 来输入不包括换行符的内容。它是否正确?但是会产生很多问题,因为它似乎存储在输入缓冲区中。输入字符串的最佳方法是什么。 fget 会产生很多问题,

        while(strcmp(buf,"quit"))
               {    
            scanf("%*[^\n]",buf);
            n=send(connected,buf,strlen(buf),0);
            if(n<0)
            {
            perror("send");
            printf("error sending");
            exit(1);
            }
            //printf("server has send\n");
            n=recv(connected,buf,100,0);
            if(n<0)
            {
            perror("recv");
            printf("error recieving");
            exit(1);
            }
            //printf("waiting to recieve something\n");
            buf[n]='\0';
            printf("client:%s\n",buf);
        }

这是在创建无限循环,同样的事情一次又一次地重复。

【问题讨论】:

    标签: c


    【解决方案1】:

    读取一行输入的更好方法是

    char line[128]; /* Or whatever. */
    
    while(fgets(stdin, line, sizeof line) != NULL)
    {
      /* Filter out whitespace before checking tokens. */
    }
    

    【讨论】:

    • 是的,我正在尝试 fgets,但它产生了一些微妙的问题。程序在第一次输入后一直在等待,可以提示可能是什么原因以及如何克服它?谢谢!
    • 是的,fgets() 是同步的,它会在继续之前等待一整行输入。不清楚您是否想要一种读取输入的非阻塞方式;那是一个不同的问题。 :)
    【解决方案2】:

    如果您遇到的只是空行,请使用strcmp("\n", buffer) == 0

    您发布的正则表达式不能很好地工作,因为 C 会将 "%*[^\n]" 中的 '\n' 字符转换为文字换行符。为了让它更好地工作,您需要对斜线进行转义:"%*[^\\n]"

    不过,问题似乎也在于阅读,我建议你使用更好的功能。

    我之前使用以下代码从文件中读取任意大小的连续行。

    不过有几点说明:

    1. 完成后返回的缓冲区需要为free()d
    2. 代码每次迭代都会浪费几个字节,但这并不明显,除非BUFFER_SIZE 与行的长度相比非常小。

    然而,该代码保证会从FILE * 中读取一整行,并且将以“\n”结尾。

    /*
     * Initial size of the read buffer
     */
    #define DEFAULT_BUFFER 1024
    
    /*
     * Standard boolean type definition
     */
    typedef enum{ false = 0, true = 1 }bool;
    
    /*
     * Flags errors in pointer returning functions
     */
    bool has_err = false;
    
    /*
     * Reads the next line of text from file and returns it.
     * The line must be free()d afterwards.
     *
     * This function will segfault on binary data.
     */
    char *readLine(FILE *file){
        char *buffer   = NULL;
        char *tmp_buf  = NULL;
        bool line_read = false;
        int  iteration = 0;
        int  offset    = 0;
    
        if(file == NULL){
            fprintf(stderr, "readLine: NULL file pointer passed!\n");
            has_err = true;
    
            return NULL;
        }
    
        while(!line_read){
            if((tmp_buf = malloc(DEFAULT_BUFFER)) == NULL){
                fprintf(stderr, "readLine: Unable to allocate temporary buffer!\n");
                if(buffer != NULL)
                    free(buffer);
                has_err = true;
    
                return NULL;
            }
    
            if(fgets(tmp_buf, DEFAULT_BUFFER, file) == NULL){
                free(tmp_buf);
    
                break;
            }
    
            if(tmp_buf[strlen(tmp_buf) - 1] == '\n') /* we have an end of line */
                line_read = true;
    
            offset = DEFAULT_BUFFER * (iteration + 1);
    
            if((buffer = realloc(buffer, offset)) == NULL){
                fprintf(stderr, "readLine: Unable to reallocate buffer!\n");
                free(tmp_buf);
                has_err = true;
    
                return NULL;
            }
    
            offset = DEFAULT_BUFFER * iteration - iteration;
    
            if(memcpy(buffer + offset, tmp_buf, DEFAULT_BUFFER) == NULL){
                fprintf(stderr, "readLine: Cannot copy to buffer\n");
                free(tmp_buf);
                if(buffer != NULL)
                    free(buffer);
                has_err = true;
    
                return NULL;
            }
    
            free(tmp_buf);
            iteration++;
        }
    
        return buffer;
    }
    

    【讨论】:

    • offset = DEFAULT_BUFFER * 迭代 - 迭代;这行应该是简单的:offset=DEFAULT_BUFFER *iteration
    • C 会将 "%*[^\n]" 中的 '\n' 字符转换为文字换行符。为了让它更好地工作,您需要对斜杠进行转义:“%*[^\\n]”。你能解释一下你的上述几行吗?如何 %*[^\\n] 比 %*[^\\n] 更好用?
    • 你提到代码每次迭代都会浪费一定数量的字节。我没有看到任何这样的浪费。你能指出这样的浪费在哪里吗?
    【解决方案3】:

    如果您的开发环境支持,您也可以使用getline()

    【讨论】:

      【解决方案4】:

      scanf("%*[^\n]",buf);有两个问题:

      1. 说明符中的星号导致值被扫描,但不被存储。
      2. 它会向上扫描直到下一个换行符,但不使用该字符。这意味着第一个调用之后的每个调用都不会读取任何内容。

      【讨论】:

      • 第二行中的“那个”应该替换为“那些字符”。不是吗? bcz %*[^\n] 将导致所有字符被跳过,即它们不会被消耗。还有你所说的“第一个调用之后的每个调用都不会读取任何内容”是什么意思。它是在输入缓冲区中存储新行的 bcz 吗?PLZ 解释一下。
      【解决方案5】:

      我认为您正在寻找的 scanf 是:

      scanf("%[^\n]%*c", buf);

      %[^\n] 获取您的字符串,%*c 忽略换行符。

      但是,如果你用谷歌搜索“如何不读取 c 中的字符串”,这实际上就是你得到的结果

      非阻塞输入完全是另外一回事。你可以用谷歌搜索“cbreak 模式”。但是,这是一个 unix-y 终端-y 的东西,如果你在 Windows 上,那可能没有意义。 X/Gtk/Qt 将有其他方式来做这种事情。

      【讨论】:

        猜你喜欢
        • 2021-08-20
        • 1970-01-01
        • 1970-01-01
        • 2021-07-31
        • 2022-11-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多