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

孤街浪徒 提交于 2021-02-10 15:46:26

问题


I want to create a text file with mulitple lines using system calls in C and populate it with the text provided as command line arguments.

This is what I wrote:

#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;
}

If I execute this program as:

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

It writes the whole thing into test.txt as it is. Basically, I want 'Foo' and 'Bar' in their separate lines.


回答1:


There's two problems here:

  • The way you're handling arguments and failing to allocate enough memory for the data involved,
  • Interpreting escape sequences like \n correctly since the shell will give them to you as-is, raw.
#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;
}

Note the tools used here:

  • strdup is a way quicker method of copying a C string than malloc(strlen(s)) and then copying it. That's asking for dreaded off-by-one errors.
  • FILE* performs much better because it's buffered. open() is used for low-level operations that can't be buffered. Know when to use which tool.
  • Don't be afraid to write functions that manipulate string contents. C strings are really important to understand, not fear.


来源:https://stackoverflow.com/questions/64830321/how-to-write-text-containing-newline-given-as-command-line-arguments-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!