(Решено) Разделение строк файла пополам (C) - PullRequest
0 голосов
/ 17 марта 2020

Используя только системные вызовы ввода / вывода, я должен написать программу на C, которая принимает файл в качестве входных данных и печатает на выходе его содержимое, разделяя каждую строку пополам. Более конкретно, если длина строки составляет n символов, программа должна напечатать первые n / 2 символа строки, за которыми следует «\ n», а затем вторые n / 2 символа. Я записал возможное решение, но оно работает не очень хорошо, разделяя правильные строки на половину содержимого файла и игнорируя остальные.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#define LEN 5000

void half_rows (char* f);
void freebuf (char arr[], int n);

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

    if (argc != 2)
        fprintf (stderr, "Usage %s: <file>\n", argv[0]), exit(1);

    char* file = argv[1];
    half_rows (file);

    return 0;

}

void half_rows (char* f){

    char c;
    char buf[LEN];
    int fd, nread, n, rest, up;
    if (( fd = open (f, O_RDONLY)) < 0)
        perror("opening error"), exit(1);
    int cur = lseek (fd, 0, SEEK_CUR);
    int finalpos = lseek (fd, 0, SEEK_END);
//  lseek (fd, cur, SEEK_SET);

    do{
        lseek (fd, cur, SEEK_SET);
        if ((nread = read (fd, &c, sizeof(c))) < 0)
            perror("reading error"), exit(1);
        buf[cur] = c;
        if ( buf[cur] == '\n' || buf[cur] == '\0'){
            rest = cur % 2;
            if (rest == 0)
                n = cur / 2;
            else{
                up = cur + 2 - rest;
                n = up / 2;
            }

            buf[n] = '\n';
            buf[n+1] = '\0';

        }
        ++cur;
    }while (cur < finalpos);

    write (STDOUT_FILENO, buf, finalpos);


}

Ответы [ 2 ]

1 голос
/ 17 марта 2020

Ну, вы можете позволить printf сделать все это за вас, без копирования или инъекции, или вы можете копировать или внедрять, или делать это за символом, как показывает @WilliamPursell (все в порядке), например,

С Printf

#include <stdio.h>
#include <string.h>

#define MAXC 1024       /* if you need a constant, #define one (or more) */

int main (void) {

    char line[MAXC];    /* buffer to hold entire line */

    while (fgets (line, MAXC, stdin)) {     /* read/validate line */
        int len = strlen(line);             /* get length of line */

        if (len == 1) {                     /* if line only 1-char */
            putchar (line[0]);              /* can't split 1 - output char */
            continue;                       /* get next line */
        }

        /* output first 1/2 and second 1/2 */
        printf ("%.*s\n%s", len/2, line, line + len/2);
    }
}

Использование 2 nd Буфера

#include <stdio.h>
#include <string.h>

#define MAXC 1024       /* if you need a constant, #define one (or more) */

int main (void) {

    char line[MAXC];    /* buffer to hold entire line */

    while (fgets (line, MAXC, stdin)) {     /* read/validate line */
        size_t len = strlen(line);          /* get length of line */
        char first[MAXC/2 + 1];             /* buffer to hold 1st 1/2 */

        if (len == 1) {                     /* if line only 1-char */
            putchar (line[0]);              /* can't split 1 - output char */
            continue;                       /* get next line */
        }

        memcpy (first, line, len/2);        /* copy 1st 1/2 to first */
        first[len/2] = '\n';                /* add newline (or just use puts) */
        first[len/2+1] = 0;                 /* nul-termiante */

        fputs (first, stdout);              /* output 1st 1/2 */
        fputs (line + len/2, stdout);       /* output rest */
    }
}

И то и другое эквивалентный вывод, например

Пример входного файла

$ cat dat/tosplit.txt
1234
56789
123

bc

Пример использования / Вывод

$ ./bin/splitline < dat/tosplit.txt
12
34
567
89
12
3

b
c

Всегда есть более чем один путь к Skin-the-Cat в C. Дайте мне знать, если у вас есть дополнительные вопросы.

1 голос
/ 17 марта 2020

Не пытайтесь хранить строки. Просто прочитайте файл дважды и введите новые строки при необходимости. например:

#include <stdio.h>
#include <stdlib.h>


FILE * xfopen(const char *path, const char *mode);

int main(int argc, char **argv)
{
        FILE *a, *b;
        int c;
        a = xfopen( argc > 1 ? argv[1] : "input", "r");
        b = xfopen( argc > 1 ? argv[1] : "input", "r");

        do {
                int alen = 0;
                int blen = 0;
                while( ( c = fgetc(a)) != '\n' && c != EOF ) {
                        alen += 1;
                }
                while( ( c = fgetc(b)) != '\n' && c != EOF ) {
                        if( blen++ ==alen / 2) {
                                putchar('\n');
                        }
                        putchar(c);
                }
                if( c != EOF)
                        putchar('\n');
        } while( c != EOF );

        return 0;
}

FILE *
xfopen(const char *path, const char *mode)
{
        FILE *fp = fopen(path, mode);
        if( fp == NULL ) {
                perror(path);
                exit(EXIT_FAILURE);
        }
        return fp;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...