I want to finaly learn what's up with pointers and arrays, so i made up this program:

#include <stdio.h>

int main()
{
    int cantidad_frases = 0;
    printf("Cuantas frases quieres escribir?: ");
    scanf("%d", &cantidad_frases);
    char *frases[cantidad_frases];
    for(unsigned i = 0; i < cantidad_frases; i++)
    {
        [B]for(; *frases[i]; frases[i]++)[/B]
        {
            *frases[i] = getchar();
        }
    }
    printf("\nReproduciendo las frases:\n\n");
    for(unsigned i = 0; i < cantidad_frases; i++)
    {
        printf("Frase %d:", i + 1);
        [B]for(; *frases[i]; frases[i]++)[/B]
        {
            printf("%c", *frases[i]);
        }
        printf("\n");
    }
    return 0;
}

I had no errors nor warnings at all. But program crashes after entering the cantidad_frases value and hitting enter. The problem is in the 11th line.

I really didn't know how to "refer" each letter of the words/string stored in frases.
I hope i made my question clear enough so you can help me. Any advise or (please) any specific place where they explain the whole thing about pointers and arrays is more than welcome!

Recommended Answers

All 11 Replies

This line should probably be:

char *frases[cantidad_frases];

char *frases = (char*)malloc(cantidad_frases);

So that you have allocated the memory...

for(unsigned i = 0; i < cantidad_frases; i++)
    {
        for(; *frases[i]; frases[i]++)
        {
            *frases[i] = getchar();
        }
    }

U have not assigned memory to frases.

Do

#define MAX_STR 40 // whatever u want
frases[i] = malloc(MAX_STR);

U are alos doing another mistake:

for(; *frases[i]; frases[i]++)

here frases is getting incremented. Hence the pointer advances and when later u want the inputed string u wont have it because the pointer has advanced to the end hence it contain nothing. U should do this with some temp pointer as

for(unsigned i = 0; i < cantidad_frases; i++)
    {
        frases[i] = malloc(MAX_STR);
        char *tmp = frases[i];
        for(; *tmp; tmp++)//AGAIN HERE U SHOULD MODIFY YOUR LOGIC BECAUSE frases[i] initially contains nothing. I am leaving it to you.
        {
            *tmp = getchar();
        }
    }

And in C for(unsigned i = 0; i < cantidad_frases; i++) is illegal. i must be defined before it is used, not in the for statement.

This line should probably be:

char *frases[cantidad_frases];

char *frases = (char*)malloc(cantidad_frases);

So that you have allocated the memory...

for(unsigned i = 0; i < cantidad_frases; i++)
    {
        frases[i] = malloc(MAX_STR);
        char *tmp = frases[i];
        for(; *tmp; tmp++)//AGAIN HERE U SHOULD MODIFY YOUR LOGIC BECAUSE frases[i] initially contains nothing. I am leaving it to you.
        {
            *tmp = getchar();
        }
    }

char *tmp = frases; <--- i'm confused here. Where does tmp point at?

And in C for(unsigned i = 0; i < cantidad_frases; i++) is illegal. i must be defined before it is used, not in the for statement.

I'm told in C99 is perfectly accepted?


OK so i see my fault was all about memory allocation, so im going to learn about that cause i know nothing.
However, if you had this *frases[].. let's say it cointains:
*frases[0] -> "tutorials"
*frases[1] -> "dani web"
*frases[2] -> "it discussion"

How would you refer to the w in web at frases[1]?

Thank you

How would you refer to the w in web at frases[1]?

frases[1][5];

or if you want to complicate it

*(*(frases + 1)+ 5)
frases[1][5];

or if you want to complicate it

*(*(frases + 1)+ 5)

Awesome. The complicated version...heheh yes.
frases is pointing at 0, so +1 makes it look at the second phrase. And then the * dereference symbol, would return what? The first word in the first phrase? --> *( ? ) + 5 <---- ? should be a memory adress so it can be added with 5 and then dereference returning the "w" letter. But how come just doing *(frases + 1) returns not the value but a memory address?

Instead of mallocation before user's input, isn't the way to allocate at the same time user inputs so you reserve the exact memory needed? Like in run time.

Thank you for your time, i'm learning a lot. I'm gonna focus learning memory, malloc and pointers stuff more.

I made it! It works perfectly thanks to your advices and further studying hehe. Any comments / corrections?

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

int main()
{
    int cantidad_frases = 0;
    printf("Cuantas frases quieres escribir?: ");
    scanf("%d", &cantidad_frases);                  
    getchar();                                      
    char *frases[cantidad_frases];
    for(unsigned i = 0; i < cantidad_frases; i++)
    {
        frases[i] = (char *) malloc(sizeof(char[20]));
        char *tmp = frases[i];
        printf("Escribe la frase %d: ", i+1);       
        while((*tmp = getchar()))
        {
            if(*tmp == 10)
            {
                *tmp = '\0';
                break;
            }
            tmp++;
        }
    }
    for (unsigned i = 0; i < cantidad_frases; i++)
    {
        puts(frases[i]);
    }

    return 0;
}

I was turning mad when i saw phrase one was skipped. I realized there was a remanent \n in the buffer (by the line feed in the cantidad_frases selection). So i added the getchar() after the scanf to clean that up. Is there any elegant way to do it? EDIT: other than using another input function.

Any comments / corrections?

In the C89 standard, an array must be set with a constant. Which would not allowed what you just did.

int cantidad_frases = 0;
    printf("Cuantas frases quieres escribir?: ");
    scanf("%d", &cantidad_frases);                  
    getchar();                                      
    char *frases[cantidad_frases]; /* This is not allowed in C89 */

Furthermore, there can not be mixing of variable declarations and code. All variable must be declared first in the block. Making char *frases[cantid_frases]; incorrect as well.
If you want dynamically allocated multidimensional arrays you may take a look at pointer to pointer. Example

C89 doesn't accept declaration of variable in the for loop construct.

for(unsigned i = 0; i < cantidad_frases; i++)

Variable i must be declared outside the ().

When you ask for user input, the control of the program is handled to the user. They can enter an integer (in which case an enter key has been added to the stream), they can enter a float, a char or any combination and length of those. Moreover they might just press enter or be generous with blank sequence.
Can scanf() handle that kind of conditions? The answer is no. The elegant option then is to think how would you deal with the input and design your program to accommodate for those possibilities. There's not "silver-bullet function" that will do that for you.

In the C89 standard, an array must be set with a constant. Which would not allowed what you just did.
Furthermore, there can not be mixing of variable declarations and code. All variable must be declared first in the block. Making char *frases[cantid_frases]; incorrect as well.

Ok but, i'm sorry if this sound ignorant which probably will, isn't C89 too old? I look it up and this C99 thing works with those issues, right? Why still thinking of C89? (remember i'm a beginner)

If you want dynamically allocated multidimensional arrays you may take a look at pointer to pointer. Example

I'm going to check that url and see what i can learn.

When you ask for user input, the control of the program is handled to the user. They can enter an integer (in which case an enter key has been added to the stream), they can enter a float, a char or any combination and length of those. Moreover they might just press enter or be generous with blank sequence.
Can scanf() handle that kind of conditions? The answer is no. The elegant option then is to think how would you deal with the input and design your program to accommodate for those possibilities. There's not "silver-bullet function" that will do that for you.

That is true...i'll see if i can improve that.

Thank you.

Ok but, i'm sorry if this sound ignorant which probably will, isn't C89 too old? I look it up and this C99 thing works with those issues, right? Why still thinking of C89? (remember i'm a beginner)

C89 is de facto standard for C, and it is also the base of the current C++ standard.

C89 is de facto standard for C, and it is also the base of the current C++ standard.

Uhm, so what's C99 used for?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.