c - 将字符串传递给 scanf

标签 c file scanf stdin

我正在尝试编写一个程序,根据给定的用户输入生成一个字符串,然后将该字符串传递给一个函数,该函数将 stdin 更改为虚拟文件,将字符串写入该文件,对所述文件使用 scanf,然后删除文件,但我无法将标准输入重定向到虚拟文件,对只会扩展到函数范围的最佳操作有何帮助?

int scan(const char* __restrict__ _format, ...){
    FILE* original = stdin, *mod = calloc(1, sizeof(FILE));
    mod = freopen("testFile.txt", "w+", stdin);
    fputs(_format, stdin);
    int a, b;
    scanf("%d %d", &a, &b);
    printf("%d, %d", a, b);
//    freopen(orig)
    return 1;
}

void swap(char* a, char* b) {
    if (*a != ' ' && *b != ' ') {
        char temp = *a;
        *a = *b;
        *b = temp;
    }
}

void permiate(char* str, int start, int end){
    int i;
    if(start == end){
        printf("%s\n", str);
    }else{
        for(i = start; i<=end; i++){
            swap(str+start, str + i);
            permiate(str, start + 1, end);
            swap(str + start, str + i);
        }
    }
}

int main(){
    int a, b;
    char str[]  = "1 3";

    //function to put string to stdio
    scan(str);
    scanf("%d %d", &a, &b);
    printf("%d, %d", a, b);
    return 0;
}

在有人指出 fscanf(这是一个我从未意识到的函数,因为我的老师从未介绍过它)之后,我找到了扫描函数的有效解决方案:

int scan(const char* __restrict__ _format, ...){
    int *a = malloc(sizeof(int)), i = 0;
    FILE *fp1 = fopen("testfile.txt", "w");
    fputs(_format, fp1);
    freopen("testFile.txt", "r", fp1);
    while(fscanf(fp1, "%d", &a[i]) != EOF){
        i++;
        a = realloc(a, sizeof(int)*i);
    }
    for(int j = 0; j < i; j++){
        printf("%d, ", a[j]);
    }
    fclose(fp1);

    return 1;
}

但是每当我给 str 一个像“1 2 3 4 5 6 ...”这样的值或任何超过 5 个数字的值时,如果我保留 realloc,则第 5 个数字始终为 0,如果我注释掉该行,那么就可以了。知道那是什么吗? PS我在大学的实验室只了解了数组的基本用法,没有动态内存或任何东西,所以如果我使用任何错误的东西,我会非常感激

最佳答案

好吧,我想我明白你正在尝试做什么,而且这是可行的,但我当然不会推荐它。每当您freopen()标准流之一时,都没有可移植的方法来恢复原始标准流。您可以从函数中删除original,因为它不起作用。也不要分配给 mod

话虽如此,您可以将 scan 函数编写为:

int scan(const char* __restrict__ format)
{
    int a, b;
    FILE *mod = freopen ("dat/freopenab.txt", "w", stdin);
    if (!mod) {
        perror ("freopen-mod-write");
        return 0;
    }

    fputs (format, stdin);              /* write to file as stdin */

    stdin = freopen (NULL, "r", mod);   /* reopen file "r" as stdin */
    if (!stdin) {
        perror ("freopen-stdin-read");
        return 0;
    }
    if (scanf("%d %d", &a, &b) != 2) {  /* read values from file */
        fputs ("error: read of int values failed.\n", stderr);
        return 0;
    }
    printf("%d, %d\n", a, b);           /* output resutls */

    return 1;
}

stdin 重新打开为上面的文件 "dat/freopenab.txt"format 字符串通过重新打开的 stdin 写入文件。然后再次调用freopen(),并使用NULL作为路径名,这允许您更改现有流mod的模式以读取和分配返回到 stdin (使 stdin 从文件中读取)

(注意:最好避免使用带前导下划线的变量名)

一个完整的例子是:

#include <stdio.h>

int scan(const char* __restrict__ format)
{
    int a, b;
    FILE *mod = freopen ("dat/freopenab.txt", "w", stdin);
    if (!mod) {
        perror ("freopen-mod-write");
        return 0;
    }

    fputs (format, stdin);              /* write to file as stdin */

    stdin = freopen (NULL, "r", mod);   /* reopen file "r" as stdin */
    if (!stdin) {
        perror ("freopen-stdin-read");
        return 0;
    }
    if (scanf("%d %d", &a, &b) != 2) {  /* read values from file */
        fputs ("error: read of int values failed.\n", stderr);
        return 0;
    }
    printf("%d, %d\n", a, b);           /* output resutls */

    return 1;
}

int main (void) {

    scan ("12 34\n");
}

示例使用/输出

$ ./bin/freopenab
12, 34

生成的输出/输入文件

$ cat dat/freopenab.txt
12 34

同样,没有可移植的方法将 stdin 恢复到原始状态,尽管在 Linux 上您可以使用 "/dev/tty" “/dev/stdin”。把事情看一遍,然后尝试一下。然后避免 freopen() 除非没有其他方法可以完成您需要做的事情,而只需再次使用 fopen、fclose 和 fopen

关于c - 将字符串传递给 scanf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59349659/

相关文章:

c - "double free"是什么意思?

java - 为什么 fileWriter 在 bufferedWriter 和 printWriter 之前写入输出文件?

php - 服务器端文件验证不适用于 Yii.2.0

c - 使用结构在学生列表中找到最大的平均值

iphone - 在 xcode/objective-c 项目中使用 C 文件

c - 如何将 IplImage 转换为 char 数组

python - 在 C++ 中循环 "all the way through"数组是否有最佳实践?

C:从二进制文件中读取字符串

c - fgets 和 sscanf

c - sscanf 没有来自标准输入的工作空间