如何在 C 中使用参数从文本文件中打印字符?

Posted

技术标签:

【中文标题】如何在 C 中使用参数从文本文件中打印字符?【英文标题】:How to print characters from text file, using arguments, in C? 【发布时间】:2019-12-31 22:51:33 【问题描述】:

我需要使用参数-n 设置一个整数n,该参数将设置为从给定.txt 文件末尾开始打印的字符数。这需要在没有 <stdio.h> 库的情况下完成,因为它是关于系统调用的家庭作业。

我有一个程序能够接受参数-n 并打印用户指定的字符数量。但是,它会在所需的输出之后打印一个不可读的字符列表和NULLS,并导致我的终端出现故障。

#include <sys/types.h> 
#include <fcntl.h> 
#include <stdlib.h>
#include <string.h>

int main(int argc, char* argv[]) 
 
    //declaration of variables
    char buf[1000]; 
    int fd;
    int n;

    //initialising n to zero
    n = 0;

    //checking if the program run call is greater than one argument
    if(argc > 1)
    //if the second argument is equal to '-n' then take the 3rd argument (the int) and put it into n using stroll (string to long)
        if(!strncmp(argv[1], "-n", 2))
    n = atoi(argv[2]);
    

    //if n has no set value from -n, set it to 200
    if(n == 0)
    n = 200;

    // open the file for read only 
    fd = open("logfile.txt", O_RDONLY); 
    //Check if it can open and subsequent error handling
    if(fd == -1)
        char err[] = "Could not open the file";
        write(STDERR_FILENO, err, sizeof(err)-1);
        exit(1);
    

    //use lseek to place pointer n characters from the end of file and then use read to write it to the buffer
    lseek(fd, (n-(2*n)), SEEK_END);
    read(fd, buf, n);

    //write out to the standard output
    write(STDOUT_FILENO, buf, sizeof(buf)-1);

    //close the file fd and exit normally with code 0
    close(fd);
    exit(0);
    return(0);

【问题讨论】:

明显与this question有关。 n-(2*n) 那个奇怪的计算是什么? 调用read读取字符时,始终捕获返回值:r = read(...)。如果r 小于 0,则出现错误。如果 r 为 0,则您已到达文件末尾。如果r 大于0,则您已经阅读了一些字符,但是您应该使用r 的字符数而不是sizeof(buf)(当然也不是sizeof(buf)-1)。我怀疑这就是为什么你会得到奇怪的字符,但你忽略了“阅读”试图告诉你有问题的尝试。 如果文件中的最后一个字符不是换行符,那么你需要在退出程序之前输出一个换行符。顺便说一句,exit(0)return(0) 做同样的事情(在main)所以你只需要其中一个。 ...和return 0; 很常见。请注意,与 exit(0) 不同,return 0; 不是函数。 【参考方案1】:

注意:此答案是对 first version of this question 的原始答案的改编(现在暂停)

我需要使用参数 -n 设置一个整数 n。

假设命令行类似于prog.exe -n 4main(int argc, char* argv[]) 的参数将填充为:

argc == 3
argv[] == "programName.exe", "-n", "4"

argc 可以通过组合 -n4: -n4 或完全消除 -n 来减少到 2,并在代码中识别出 argv[1](第二个参数)是您需要的值的字符串表示形式,并将其转换为int 类型。

例子:

programName.exe 3

然后这样编码:

int main(int argc, char *argv[])

    char *dummy;
    int val;
    if(argc != 2)
    
        printf("Usage: prog.exe <n> where <n> is a positive integer value.\nProgram will now exit");
        return 0;
    
    // Resolve value of 2nd argument:
    val = strtol(argv[1], &dummy, 10);
    if (dummy == argv[1] || ((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE))
    
            //handle error
    
    //use val to read desired content from file
    ...

    return 0;

其他一些一般性建议:

一般来说,用户输入需要尽可能地保持可预测性。在要求用户输入可接受的内容时要明确,并拒绝任何不符合要求的内容。例如,如果一个程序需要一个数字参数,那么强制它只是那个,并拒绝其他所有内容。给定不符合要求的用户输入:

prog.exe 3 4 5

在代码中检测:

int main(int argc, char *argv[]) 

    int val = 0;
    char *dummy = NULL;

    if(argc != 2)
    
        printf("Usage: prog.exe <n> - Where <n> is an integer with value > 0\n Program will now exit.");
        return 0;
    
    val = strtol(argv[1], &dummy, 10);
    if (dummy == argv[1] || ((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE))
    
        printf("Usage: prog.exe <n> - Where <n> is an integer with value > 0\n Program will now exit.");
        return 0;

    

    ...

使用可移植函数(将lseek 替换为fseek,将open 替换为fopen 等)(阅读this for an example of the reason why)这是对您的代码的改编你所描述的你需要它来做,包括使用prog.exe -n &lt;n&gt; 参数,(argv == 3)。

int main(int argc, char *argv[])

    char *dummy;
    char buf[1000]; 
    int n;    


    //initialising n to zero
    n = 0;

    //checking if the program run call is greater than one argument
    if(argc != 3)
    
        printf("Usage: prog.exe -n <n> - Where <n> is an integer with value > 0\n Program will now exit.");
       return 0;
    
    n = strtol(argv[2], &dummy, 10);
    if (dummy == argv[2] || ((n == LONG_MIN || n == LONG_MAX) && errno == ERANGE))
    
        printf("Usage: prog.exe <n> - Where <n> is an integer with value > 0\n Program will now exit.");
        return 0;

    


    // open the file for read only 
    FILE *fd = fopen(".\\data.txt", "r");

    //Check if it can open and subsequent error handling
    if(!fd)
    
        char err[] = "Could not open the file";
        fputs(err, stdout);
        return 0;
    

    //use lseek to place pointer n characters from the end of file and then use read to write it to the buffer
    fseek(fd, (n-(2*n)), SEEK_END);
    if(fgets(buf, n, fd))
    
        //write out to the standard output
        fwrite(buf, 1, n, stdout);
    
    else 
    
        ;//handle error
    

    //close the file fd and exit normally with code 0
    fclose(fd);

    return(0);

【讨论】:

以上是关于如何在 C 中使用参数从文本文件中打印字符?的主要内容,如果未能解决你的问题,请参考以下文章

labview如何读取文本文档中某一行的字符串

C语言如何判断文本文档的结束

如何用Java或C语言解析二进制文件为文本文件?

C语言如何把以下格式的文本读出来打印到屏幕上

c语言 如何读取中文字符串

C语言:从键盘输入一篇英文文本,统计每个英文字母(分大小写)及空格、数字、回车和其他字符,咋编?