【问题标题】:Getting unlimited input in C?在 C 中获得无限输入?
【发布时间】:2016-06-30 01:38:45
【问题描述】:

所以我正在尝试编写一个允许用户输入无限数量的字符的函数。例如:

char string[100]

将输入限制为 100 个字符。

我目前的代码是:

#include<stdio.h>

char* uinput(){
    char *string, *current;
    int counter = 0;
    string = (char *) malloc(10 * sizeof(char));
    do{
        realloc(string, counter * sizeof(char));
        current = string + counter;
        *current = getchar();
        counter++;
    }while(*current != '\n');
    return string;
}

int main(){
    char *s;
    s = uinput();
    printf("\nYou entered: %s", *s);
    return 0;
}

我是指针的新手,所以我不确定为什么这不起作用(程序崩溃)。我正在尝试做的是继续读取一个字符并继续重新定位字符串指针,以便字节量不断增加,直到用户按下回车键('\n')。

谢谢 〜拉夫

【问题讨论】:

  • 函数getline 是一个简单的答案。它最初是一个 glibc 扩展(即不是 C 标准库),但它也应该在 mingw 下得到支持。如果您需要担心跨平台,那么可以使用 fgets 和 realloc 重新实现它。
  • @rafaelThedoublemaster 代码有很多问题,我正在写答案。

标签: c windows input mingw


【解决方案1】:

这个方法是理智的,但是有一些小细节是错误的。如果您在启用警告的情况下进行编译,您会注意到您缺少&lt;stdlib.h&gt;;您也将 第一个字符 提供给printf,而不是指向缓冲区的指针。

然后有一个明显的错误,您的大小重置为0,并且您是casting the return value of malloc,使用char 存储getchar() 的结果也是错误的,因为您无法检查EOF。您没有保存 realloced 指针;并且您没有正确终止字符串。在次要细节上,您希望将每个realloc 中的缓冲区大小加倍,因为realloc 需要潜在地复制整行,因此随着行长度的增长,它会随着时间的推移变得越来越慢。

因此我们得到:

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

char* uinput() {
    char *string;
    // number of characters in the buffer
    size_t counter = 0;

    // size of allocated buffer
    size_t allocated = 16;
       
    int c;
    string = malloc(allocated);  // sizeof(char) is 1
    do {
        c = getchar();
        if (c == EOF) {
            break;
        }
        // if our buffer is too small, double the allocation 
        if (counter + 2 <= allocated) {
            size_t new_size = allocated * 2;
            char *new_buffer = realloc(string, new_size);
            if (! new_buffer) {
                // out of memory? try smaller increment
                new_size = allocated + 16;
                new_buffer = realloc(string, new_size);
                if (! new_buffer) {
                    // really out of memory: free old block
                    free(string);
                    return NULL;
                }
            }
            allocated = new_size;
            string = new_buffer;
        }
        // store the character
        string[counter++] = c;
    } while (c != '\n');

    // terminate the buffer properly
    string[counter - 1] = '\0';
    return string;
}

int main() {
    char *s = uinput();
    if (!s) {
        // possibly out of memory in uinput
        perror("Error reading input");
        exit(EXIT_FAILURE);
    }
    printf("\nYou entered: %s", s);
    free(s);
    return EXIT_SUCCESS;
}

【讨论】:

  • 希望我的 UB 没有做太多。我想我必须提供一个 PD getline 实现:D
  • 哇,感谢您的回答:D 我需要了解更多关于 C 的知识。顺便说一句,您能解释一下 EOF 吗?我第一次看到它
  • 文件结束。如果您在 Linux 中按 ctrl-d,在 Windows 中按 ctrl-z;或者如果你想对文件使用这种方法(你可以使用fgetc而不是getchar
  • 永远不要像这样调用reallocname = realloc(name, newSize) - 它失败然后你有内存泄漏 - 使用临时指针直到你知道realloc 是否成功。
【解决方案2】:

使用getcharmallocrealloc 读取无限输入字符串

声明String类型,也可以使用char *

// String type
typedef char *String;

我写了这个函数来加入字符串末尾的字符

/**
 * Join the Char into end of String
 *
 * @param string - String
 * @param c - joined char
 */
void String_joinChar(String *string, const char c)
{
  const size_t length = strlen(*string);
  (*string) = (String)realloc((*string), sizeof(char) * (length + 2));
  (*string)[length] = c;
  (*string)[length + 1] = '\0';
}

此函数用于输入字符串,它使用getchar从键盘读取字符并将其加入当前字符串的末尾。

/**
 * Input String
 *
 * @return Inputed String
 */
String String_input()
{
  String string = (String)malloc(sizeof(char));
  strcpy(string, "");

  char cursor;
  fflush(stdin);
  while ((cursor = getchar()) != '\n' && cursor != EOF)
  {
    String_joinChar(&string, cursor);
  }

  return string;
}

使用char *mallocrealloc的原因,我们必须释放它

/**
 * Destroy String
 *
 * @param string - Destroyed String
 */
void String_destroy(String string)
{
  free(string);
}

现在我们就用它!!

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

int main()
{
  String string = String_input();
  printf("\n%s\n", string);
  String_destroy(string);
  return 0;
}

希望对你有用!

【讨论】:

  • int cursor!!
【解决方案3】:

另一种方法是使用fgets(),它从输入流中获取一个字符串到一个大小合适的缓冲区中;如果输入完整,则字符串以\n 结尾;如果没有,那么它不会。所以你可以循环调用 fgets 直到最后有一个 EOL 字符,然后根据你的程序对输入的处理,你可以决定是继续重新分配还是一次处理输入。

【讨论】:

    【解决方案4】:

    您可以尝试以下方法:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct person{
        char *name;
    }pers;
    
    void addMem(void);
    
    int main(void){
        addMem();
    
        printf("\nYour name is:>  %s\n",pers.name);
        free(pers.name);
        pers.name = NULL;
        return 0;
    }
    
    void addMem(void){
        unsigned int length = 6;
        size_t newLength = 0;
        unsigned int newSize = 0;
        unsigned int i =0;
        char *name;
        int c;
    
        name = malloc(length);
        if(name == NULL){
            exit(1);
        }
        newSize = length;
    
        printf("Enter your name:>  ");
    
        while ((c = getchar()) != '\n' && c!=EOF){
            name[i++]=(char)c;
    
            if(i == newSize){
                newSize = i+length;
                name = realloc(name, newSize);
            }
        }
    
        name[i] = '\0';
    
        newLength = strlen(name)+1;
        pers.name = malloc(newLength);
    
        memcpy(pers.name, name, newLength);
    
        free(name);
        name = NULL;
    }
    

    【讨论】:

    • 永远不要像这样调用reallocname = realloc(name, newSize) - 它失败然后你有内存泄漏 - 使用临时指针直到你知道realloc 是否成功。
    【解决方案5】:

    好的,我认为这是问题

    你正在重新分配

    realloc(string, counter * sizeof(char));

    第一次迭代中字符串的大小是多少?它将是0

    现在您正在写入一个分配了 0 个字节并因此出现段错误的指针。

    将其更改为 while loop 可以帮助修复它。您也可以更改计数器的初始值来修复它

    【讨论】:

    • 确实很好:D 我只是尝试将计数器更改为 1,但程序仍然崩溃(没有响应)
    猜你喜欢
    • 1970-01-01
    • 2015-07-25
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2012-03-08
    • 1970-01-01
    • 1970-01-01
    • 2012-11-14
    相关资源
    最近更新 更多