如何在 C 中编写包含作为命令行参数给出的换行符的文本?

How to write text containing newline given as command line arguments in C?

我想使用 C 中的系统调用创建一个包含多行的文本文件,并使用作为命令行参数提供的文本填充它。

这是我写的:

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

#define MAX_SZ 1024

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("Invalid Number of arguments\n");
        printf("USAGE: ./a.out file_name \"msg\"\n");
    } else {
        int fd_creat, fd_open, fd_write;
        char file_name[MAX_SZ];
        char *msg = (char *)malloc(strlen(argv[2]) * sizeof(char));
        strcpy(file_name, argv[1]);
        fd_creat = creat(file_name, 0777);
        if (fd_creat < 2) {
            printf("ERROR: File could not be created\n");
        } else {
            fd_open = open(file_name, O_WRONLY);
            strcpy(msg, argv[2]);
            fd_write = write(fd_open, msg, strlen(msg));
            close(fd_open);
        }
    }
    return 0;
}

如果我将这个程序执行为:

./a.out test.txt "Foo\nBar"

它将整个内容按原样写入 test.txt。基本上,我希望 'Foo' 和 'Bar' 在它们各自的行中。

这里有两个问题:

  • 您处理参数的方式以及未能为所涉及的数据分配足够的内存,
  • 正确解释像 \n 这样的转义序列,因为 shell 会按原样提供它们,原始的。
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

// This moves overlapping strings from src -> dest but only
// if dest is before src
void cc_str_drag(char* dest, char* src) {
    while (*dest) {
        *dest = *src;
        ++dest;
        ++src;
    }
}

// This interprets the \n sequence and can be extended to handle others, like
// \t, \, or even \g.
void cc_interpret(char* str) {
    for (;*str; ++str) {
        // If this is a sequence start...
        if (*str == '\') {
            // ...find out which one...
            switch (str[1]) {
                case 'n':
                    // Shift back...
                    cc_str_drag(str, &str[1]);
                    // ...and replace it.
                    *str = '\n';
                    break;
            }
        }
    }
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("Invalid Number of arguments\n");

        // Remember argv[0] is the name of the program
        printf("USAGE: %s file_name \"msg\"\n", argv[0]);
        return -1;
    }

    // Since it's not the 1970s, use fopen() and FILE*
    FILE* output = fopen(argv[1], "w");

    if (!output) {
        printf("ERROR: File could not be created\n");
        return -2;
    }

    // Copying here to avoid tampering with argv
    char* str = strdup(argv[2]);

    // Replace any escape sequences
    cc_interpret(str);

    // Then just dump it directly into the file
    fwrite(str, 1, strlen(str), output);

    fclose(output);

    return 0;
}

注意这里使用的工具:

  • strdup 是一种比 malloc(strlen(s)) 然后复制它更快的复制 C 字符串的方法。这要求可怕的 逐一 错误。
  • FILE* 性能更好,因为它有缓冲。 open() 用于无法缓冲的低级操作。知道什么时候使用哪个工具。
  • 不要害怕编写操作字符串内容的函数。 C字符串真的很重要,要理解,不要害怕。