如何接受未确定大小的字符串输入?

时间:2015-09-23 13:11:21

标签: c string

这里有一点python vs C。

我刚刚在python中编写了一个程序来进行计算,该函数接受所有数字作为字符串输入,这样就可以处理非常庞大的数字。

无论如何在C中执行此操作而未指定字符串长度的确切限制吗?

所以我在以下基本转换器函数中有一个100个字符的字符串限制。 (目前仅转换为基数10)

    #include <stdio.h>
    #include <string.h>
    #include <stdbool.h>
    #include <math.h>

char SYMBOLS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };

//just testing how to access the SYMBOLS[]
int print_symbols() {


    printf("Printing individual characters at a time:\n");
    for (int i = 0; i < strlen(SYMBOLS); i++)
    {
        printf("%c ",SYMBOLS[i]);
    }
    printf("\nLength/num of symbols: %d", strlen(SYMBOLS));

    printf("\n\nPrinting the whole string at once:\n");
    printf("%s", SYMBOLS);
    printf("\n\n");

    return 0;
}

//accepts a string to display a prompt to the user and returns input
char* input(char prompt[]) {
    static char received[100];
    printf("%s", prompt);
    fgets(received,100,stdin);
    //Find the return charage and replace with string terminator
    for (int i = 0; i < strlen(received); i++)
    {
        if (received[i] == '\n') {
            received[i] = '\0';
        }
    }

    return received;
}

char* reverse(char string[]) {
    static char reversed[100];
    int len = strlen(string);
    for (int i = 0; i < len; i++)
    {
        reversed[len - 1 - i] = string[i];
    }
    return reversed;
}

char* from_base_10(char num[], int base) {
    //NOTE: this function isnt finished and is not actually use yet....
    static char new_num[100];
    int numInt = atoi(num);
    int div;
    int rem;
    int count=0;

    if (base>36)
    {
        strcpy(new_num,"\nERROR: Base can not be higher than 36\n");
        return new_num;
    }

    while (numInt>0)
    {
        div = numInt / base;
        rem = numInt % base;
        //printf("%d \\ %d = %d remainder %d symbol = %c\n",numInt, base, div, rem, SYMBOLS[rem]);

        //can not use strcpy or strcat as a single char has no '\0' terminator
        new_num[count] = SYMBOLS[rem];

        count++;
        numInt = div;
    }
    new_num[count] = '\0';//finish the new string off

    //and now the new string has to be reversed
    strcpy(new_num, reverse(new_num));

    return new_num;
}

char* to_base_10(char num[], int base) {
    static char new_num[100];
    int len = strlen(num);
    int power;
    int total=0;
    char digit[2];//to use atoi() on a single char we still need a '\0' so didgit needs to be a 2 char string

    if (base > 36)
    {
        strcpy(new_num, "ERROR: Base can not be higher than 36.");
        return new_num;
    }

    for (int i = 0; i < len; i++)
    {
        power = len - 1 - i;
        digit[0] = num[i];
        //add digit times base to the power of its position in the number
        total += atoi(digit) * pow((double)base, (double)power);
    }
    printf("\n New Number is : %d\n", total);

    itoa(total, new_num, 10); //LOL and at this point I findout this function actually converts base at the same time.
    return new_num;
}


int main() {
    char* result;//accapts strings from input()
    result = "";//needs a value for strcmp to use it

    while (strcmp(result, "exit")!=0)
    {
        printf("\n\n\n Brads Math Functions \n");
        printf("======================\n");
        printf("Enter [exit] to quit.\n");
        printf("Enter [base] to convert numbers from one base to another.\n");
        result = input("\nEnter an option from the menu:");

        if (strcmp(result,"base")==0)
        {
            char num[100];
            strcpy(num, result=input("Enter a number:"));
            int end = atoi( input("Enter base:"));
            printf("\nResult: %s\n", to_base_10(num, end));
        }
    }

    printf("\n");
    return 0;
}

2 个答案:

答案 0 :(得分:3)

首先,现有的计算机不允许您存储&#34;无限制&#34;值。事实上,考虑到当前的宇宙可能是有限的,在我们的现实中没有办法做到这一点。

但是,如果你想存储&#34;大&#34;数字(&#34;大&#34;表示超过C中任何现有数字数据类型的数字),您可能需要考虑将它们存储为char数组。同样,您的应用程序已被限制为虚拟地址空间(请参阅this)。

您可能需要查看Dynamic Memory Allocation in C,这可能对您有所帮助。

答案 1 :(得分:0)

接受“无限”大小的字符串输入:

getline(char **lineptr, size_t *n, FILE *stream),不是标准的,但通常在* nix中。它将根据需要重新分配内存。样本source code

或者根据需要编写一个关于fgets/fgetc重新分配内存的辅助函数。样本code

使用接受“无限”大小的字符串输入的函数时要小心。从根本上说,这是未来的安全漏洞,因为代码可以控制外部数据或用户压倒资源。

而是建议限制,但要输入一个较大的值,字符串输入。

#define N 1000000
char *ptr = malloc(N);
assert(ptr);
fgets(p, N, stdin);
...
free(ptr); 

注意:许多C内存分配函数的实现只分配,而不是“使用”内存,直到需要。因此,如果不是完全需要,大量分配不会耗尽内存。