0

So, I've been searching this around StackOverflow for awhile now but none of the semi-related posts are a solution to mine, so I hope anyone can help :)

So what I wanna do is transfer a .txt file, that has the following content on it:

1 5 8

2 4 6 9

5 7 

(per example)

So, what I want to know is:

  1. How to transfer the .txt to allocated memory using malloc;

  2. I have to read each line separately and extract the numbers, then to compare with the contents of a structure with the ID cooresponding with the numbers in the .txt file.

  3. If I transfer the contents of the .txt to the array (using malloc), will it still have the '\n' on the array, so I can distinguish the lines?

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
Zetsuno
  • 97
  • 1
  • 9
  • Apparently a `fgets()` + `strtol()` combination would be perfect for this task. Is the file irregular like the example? I mean, every line contains a different number of values? – Iharob Al Asimi Apr 12 '15 at 19:47
  • I wanted the separated values of each line, ex: 1, 5 and 8 for line 1, would strtol place 158 on a string? Because if that was the case, then that would help. But still how would I pass to the next line? Thanks by the way :), And yes. the file with values is randomly generated, with atleast 2 values per line and I can guarantee there won't be a value above 9, for the record. – Zetsuno Apr 12 '15 at 19:50
  • What? you mean each line is a single number? and the digits are separated with spaces? – Iharob Al Asimi Apr 12 '15 at 19:52
  • No, line 1 has three numbers: 1, 5 and 8. I need to separate them individually. But, if strtol placed the value 158 on a string, i could just get the numbers individually. – Zetsuno Apr 12 '15 at 19:53
  • can you say anything about the expected file size? – mfro Apr 12 '15 at 19:53
  • I'd say no more than 300bytes – Zetsuno Apr 12 '15 at 19:58
  • But each line has a different number of numbers then? – Iharob Al Asimi Apr 12 '15 at 19:59
  • yes, a number of numbers given by the user, but the numbers itself are between 1 and 9 – Zetsuno Apr 12 '15 at 20:02

1 Answers1

0

Since the values go from 1 to 9, you can use 0 as a sentinel for each row, that way you don't need to predict or store the number of numbers in each line, you just store all the numbers that appear, and the add a 0 at the end that will help you know where the numbers end, something identical to how c handles strings.

The following code does what I describe

#include <string.h>
#include <stdlib.h>
#include <ctype.h>

int
appendvalue(int ***values, int row, int column, int value)
 {
    void *pointer;

    pointer = realloc(values[0][row], (1 + column) * sizeof(int));
    if (pointer == NULL)
     {
        fprintf(stderr, "warning: allocating memory\n");
        return 0;
     }
    values[0][row]         = pointer;
    values[0][row][column] = value;

    return 1 + column;
 }

int
main(void)
 {
    FILE  *file;
    char   buffer[100];
    char  *line;
    int  **values;
    int    row;

    file = fopen("input.txt", "r");
    if (file == NULL)
     {
        fprintf(stderr, "error opening the file\n");
        return -1;
     }
    values    = NULL;
    row = 0;
    while ((line = fgets(buffer, sizeof(buffer), file)) != NULL)
     {
        void  *pointer;
        size_t column;

        while (isspace(*line) != 0)
            line++;
        if (*line == '\0') /* empty line -- skip */
            continue;
        pointer = realloc(values, (row + 1) * sizeof(int *));
        if (pointer == NULL)
         {
            fprintf(stderr, "error allocating memory\n");
            return -1;
         }
        values      = pointer;
        values[row] = NULL;
        column      = 0;
        while ((*line != '\0') && (*line != '\n'))
         {
            if (isspace(*line) == 0)
                column = appendvalue(&values, row, column, *line - '0');
            ++line;
         }
        column = appendvalue(&values, row, column, 0);

        row += 1;
     }
    /* let's print each row to check */
    for (--row ; row >= 0 ; --row)
     {
        size_t index;
        for (index = 0 ; values[row][index] != 0 ; ++index)
         {
            printf("%d, ", values[row][index]);
         }
        printf("\n");
        free(values[row]);
     }
    free(values);
    return 0;
 }
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • The thing is, I can't change the code that generates the file, so I wont be able to place the 0 where the line ends. – Zetsuno Apr 12 '15 at 20:32
  • The `0` will be placed in the code that reads the file, i.e. the code above, it's placed in the heap space you allocated with `realloc()` so you please test the code, tell me if it does what you need, try to understand the part that prints the numbers, Y así vas a entender bien como usar el arreglo `values`. – Iharob Al Asimi Apr 12 '15 at 20:35
  • Oh, I get it, i'm gonna try it and i'll tell you something, thanks a lot for your time, patience and knowledge :] – Zetsuno Apr 12 '15 at 20:40
  • Can you explain what you did in last part of the code? I thought you placed all values into a matrix, but i'm kinda confused, specialy at the part of the variable 'index'. The values are in a matrix with [row] rows but i don't quite understand the index part, sorry :c, I'm still new at c – Zetsuno Apr 12 '15 at 22:13
  • @DanielFernandes It's not a matrix, it's a different kind of container, the last part you go through the "*rows*" of the container, but each one has a different number of items, so you scan the items until the `item[index] == 0` condition is satisfied, because that would mean that there are no more items. – Iharob Al Asimi Apr 12 '15 at 22:16
  • Oh, so index is pretty much the number of the column that changes from line to line, I see, thanks! – Zetsuno Apr 12 '15 at 22:19
  • @DanielFernandes If the solutions is what you needed, then you can mark this answer as accepted by clicking the check mark. – Iharob Al Asimi Apr 12 '15 at 22:31
  • It's working fine! The output is reversed though. first line of the .txt is the last of the output, etc.. Guess I just need to ajust the for cycle right? – Zetsuno Apr 12 '15 at 22:44
  • Or is it the whole 'container' that has the values reversed? – Zetsuno Apr 12 '15 at 22:50
  • @DanielFernandes it's because it's printing in reverse order, if you change `for (--row , ... )` to `int k; for (k = 0 ; k < row ; ++k)` and change `row` with `k` inside the loop, it will print in the wanted order, the container is ok, it's up to you how to use it, you just need to know that a row has an unespecified number of elements, and you need to search for the `0` element to know when they are over. – Iharob Al Asimi Apr 12 '15 at 23:18
  • Yep, working like a charm! Thanks a lot ! You're a real lifesaver! – Zetsuno Apr 12 '15 at 23:32
  • Just a quick question. The objective of this thing is to later transfer/add/delete numbers (one at a time) from line (ex: want to transfer the '1' from line 1 to line 3 / Want to delete the 5 from line 1 / want to add a number to the line 1'). How should I proceed? Realocate more space with realoc? – Zetsuno Apr 13 '15 at 08:49
  • Yes, exatcly by using the `appendvalue()` function, deleting is tricky though, you will probably need `memmove()`. – Iharob Al Asimi Apr 13 '15 at 11:48
  • Could you help me in that part, my level of knowledge still hasn't reached that level (on the part that requires dealing with memory to that extent...sorry for the trouble and thanks a lot for everything ! – Zetsuno Apr 13 '15 at 13:03