【问题标题】:passing string to scanf将字符串传递给 scanf
【发布时间】:2020-04-08 12:07:49
【问题描述】:

我正在尝试制作一个程序,在给定用户输入的情况下生成一个字符串,然后将该字符串传递给一个函数,该函数将标准输入更改为一个虚拟文件,将字符串写入文件,在所述文件上使用 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 我在 uni 的实验室只涉及数组的基本用途,没有动态内存或任何东西,所以如果我使用了任何错误的东西,它会非常受欢迎

【问题讨论】:

  • 你需要把你的代码放在这里并展示你已经做了什么。
  • 你到底对mod in FILE* original = stdin, *mod = calloc(1, sizeof(FILE)); 做了什么?不需要分配,实际上分配一个FILE* 指针来保存来自freopen 的返回是错误的.只需FILE* original = stdin, *mod;
  • @DavidC.Rankin 我尝试使用它,它确实将字符串写入文件,但是当我使用 scanf 时,它不会像往常一样要求输入,但它也不会从文件中读取,它只是不理会这些值,并没有像预期的那样修改它们,而且我似乎无法将 freopen() 恢复正常,有什么想法吗?
  • 这听起来像XY Problem(又名What is the XY Problem?)。例如,您可以使用fscanf() 而不是scanf(),并在您想要从标准输入读取时传递stdin,当您想要从中读取新创建的文件时传递一个文件流。仔细想想你的需求是什么——然后才考虑如何解决问题。

标签: c file scanf stdin


【解决方案1】:

好的,我想我理解你想要做什么,而且它是可行的,但我当然不会推荐它。每当您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, and fopen。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 2016-06-01
    • 2011-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多