1

I am having trouble storing strings into a 2d array using scanf.

To illustrate, this is the input the program accepts:

p2/src/stuff:5:
p3/src/stuff:5:
p4/src/stuff:6:

So I want to be able to split the strings and numbers by colons and store them separately. So ideally, my 2d array would look like this for strings:

[["p2/src/stuff"], ["p3/src/stuff"], ["p4/src/stuff"]]

Numbers can be stored in a 1d array.

Here is what I have so far:

    int main() {
        char *str;
        char *i;

        int n = 1;
        while (n == 1) {
                n = scanf("%m[^':']:%m[^':']:", &str, &i);
        }
        printf("# inputs read: %d\n", n);
        printf("%s\n", str);
        printf("%s\n", i);
    }

Here it only prints the first line:

p2/src/stuff
5

Should I have an iterator that dose pointer arithmetic? I'm not familiar with pointer arithmetic.

2 Answers 2

2

scanf returns the number of items scanned. In this case it would be 2 instead of 1. Here a return of 1 would indicate a problem during the scan.
The %m specifier allocates memory to the pointers. Using a single pair of pointers, they should be freed in eadh iteration of the loop. You could use an array of pointers to store each of the inputs.
The scanset does not need the single quotes [^':']. If you are scanning for all characters that are not a colon [^:] will work.
EOF will terminate the while loop so if you are reading from a file, it will stop at the end of the file. Reading from stdin could be terminated using Ctrl+D (Linux) or Ctrl+Z (Windows).

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

int main() {
    char *str;
    char *i;
    int n;
    while ( ( n = scanf("%m[^:]:%m[^:]:", &str, &i)) == 2) {
        printf("# inputs read: %d\n", n);
        printf("%s\n", str);
        printf("%s\n", i);
        free ( str);
        free ( i);
    }
    return 0;
}

EDIT:
This uses an array of pointers to collect several inputs to the str and i arrays.

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

int main() {
    char *str[10];// array of pointers
    char *i[10];

    int each = 0;
    int loop = 0;
    int n = 0;
    while ( ( n = scanf("%m[^:]:%m[^:]:", &str[each], &i[each])) == 2) {
        printf("# inputs read: %d\n", n);
        printf("%s\n", str[each]);
        printf("%s\n", i[each]);
        each++;
        if ( each > 9) {
            break;//too many inputs for array size
        }
    }
    for ( loop = 0; loop < each; loop++) {
        printf ( "str[%d]=%s\n", loop, str[loop]);//print all the str inputs
    }
    for ( loop = 0; loop < each; loop++) {
        printf ( "i[%d]=%s\n", loop, i[loop]);//print all the i inputs
    }
    for ( loop = 0; loop < each; loop++) {//free memory
        free ( str[loop]);
        free ( i[loop]);
    }
    return 0;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Wow. That is amazingly bad. No wonder that's not in the C11 standard. Thanks for there reference.
2

You have a few issues here.

First, while you should be using character pointers, you never allocate any memory for them. Next, when you use scanf, you should not be passing the address of the pointers but the pointers themselves. This is an easy mistake to make since you must pass the address when using scanf with integer types.

 int main() {
    char str[255];
    char i[255];

    int n = 1;
    while (n == 1) {
            n = scanf("%m[^':']:%m[^':']:", str, i);
    }
    printf("# inputs read: %d\n", n);
    printf("%s\n", str);
    printf("%s\n", i);
}

1 Comment

By the way, I've taken the easy road of arbitrarily making the strings 255 bytes each. You really ought to use a function that allows you to limit the input to prevent an overflow from occurring should someone send you unexpected input.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.