LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Pointer Arrays (https://www.linuxquestions.org/questions/programming-9/pointer-arrays-599321/)

JMJ_coder 11-13-2007 09:41 AM

Pointer Arrays
 
Hello,

(Note: This problem comes straight from my course textbook. But, it is not for a grade, nor is it homework. I do the exercises to learn the material, but the professor doesn't assign them - he doesn't even mention them)

This is from the chapter on C-Strings:

6. Write a function that will accept ten lines of user-input and store the entered lines as ten individual C-strings. Us a pointer array in your function.

Here is what I have:

Code:

#include <iostream>

int main()
{

  int i;
  char *textl[10];
  char temp[81];


  // here is the function to read the lines in

  for (i=0; i<10; i++){
    std::cout<<"Enter a line of text: ";
    std::cin.getline(temp, 81);
    textl[i] = temp;
  }


  // this will display the lines

  for (i=0; i<10; i++){
    std::cout<<textl[i]<<std::endl;
  }

  return 0;
}

With the above, I get 10 lines of the last entered text. I assume that textl is just getting the address of temp, which stays the same, but the information stored there changes, and displays. So I thought I would cut out the middle man and just go straight to textl with the following:


Code:

#include <iostream>

int main()
{

  int i;
  char *textl[10];
 

  // here is the function to read the lines in

  for (i=0; i<10; i++){
    std::cout<<"Enter a line of text: ";
    std::cin.getline(textl[i], 81);
  }


  // this will display the lines

  for (i=0; i<10; i++){
    std::cout<<textl[i]<<std::endl;
  }

  return 0;
}

But with this, I get a segmentation fault after I enter the second line of text.


This is the point where I am stuck. Any help would be appreciated.

David1357 11-13-2007 10:49 AM

Re: Pointer Arrays
 
Quote:

Originally Posted by JMJ_coder (Post 2957556)
Code:

    char *textl[10];
But with this, I get a segmentation fault after I enter the second line of text.

This is the point where I am stuck. Any help would be appreciated.

You should start by looking more closely at this line.

JMJ_coder 11-13-2007 12:34 PM

Hello,

Quote:

Originally Posted by David1357 (Post 2957626)
You should start by looking more closely at this line.

:confused: That is how the book says to declare it.

PAix 11-13-2007 02:34 PM

Forgive me for saying so, but you are wrong in what you just said,
Quote:

That is how the book says to declare it.
, but then the book also told you how to write it and you were prepared to change that, so perhaps you have to change the structure/s also and David has pointed you in the right direction. After all, you don't make a motorbike by taking two wheels off of a car, now do you? I think that David is giving you the direction so that you can have a bit of think about it for yourself. Otherwise what's the point. I'm sure that David has it sorted, but then he isn't in the seat trying to expand his learning in this area, is he? There is going to be a number of people out there taking your example and solving the problem for themselves,. You know that learning isn't to do with asking for answers it's asking for direction. Good luck.

PAix

JMJ_coder 11-13-2007 03:24 PM

Hello,

The problem tells me to use a pointer array. And the book says:

Quote:

The declaration of an array of character pointers is an extremely useful extension to single string pointer declarations. For example, the declaration

char *seasons[4];

creates an array of four elements, where each element is a pointer to a character. As individuals pointers, each pointer can be assigned to point to a string using string assignment statements. Thus the statements
seasons[0] = "Winter";
seasons[1] = "Spring";
seasons[2] = "Summer";
seasons[3] = "Fall"; // note: string lengths may differ
set appropriate addresses into the respective pointers.

A First Book of C++: From Here to There - by Gary J. Bronson
pg. 481


I am sure that you guys know what exactly is wrong. And you're right, I don't want just an answer, I want mostly an understanding. But the clue given to me isn't jump-starting my brain. I just don't see anything wrong with my pointer array declaration, sorry. :scratch:

David1357 11-13-2007 05:47 PM

Quote:

Originally Posted by JMJ_coder (Post 2957878)
I am sure that you guys know what exactly is wrong. And you're right, I don't want just an answer, I want mostly an understanding. But the clue given to me isn't jump-starting my brain. I just don't see anything wrong with my pointer array declaration, sorry. :scratch:

Well, we do this for a living.

Quote:

Originally Posted by JMJ_coder (Post 2957556)
Here is what I have:

Code:

  char *textl[10];
  char temp[81];


What are the values of text1[0], text1[1], ..., text1[9]?
What is the value of temp?
Did you even know that temp could have a value?

This is C/C++, not BASIC, so you have to do some heavy lifting. Look up the functions malloc, calloc, and free in your textbook. They will probably have some examples of what you are looking for.

You will also want to look at strcpy and memcpy. There is an important difference between the two.

genix 11-13-2007 07:19 PM

This exercise in pure C is far from trivial. You would help yourself by learning exactly what pointers are and how they work. For example if you dont understand what this does.

Code:

char array[30];
char **a;
char *p;
p = &array[0];


while ( ( c = getc(stdin) ) != '\n' )
{
  *p++ = c;
}
*p = '\0';
p = array;
a[0] = p;
cout << a[0] << endl;

And why it would segfault after 30 chars, and even more importantly what you would have to do to make it handle as many chars as you input then you really need to sit down and understand this stuff, really try to understand what all those things ive written above do. Once you understand pointers and like David said malloc and calloc, you can then move on to using C++'s new and delete.
You said above that you 'assume', with a programming language like C/C++ you need to know. The best advice i can give you is, "learn the fundamentals"

NOW about your question.

Code:

When you declare *textl[10] you are declaring an array of pointers to type char.
When you declare char temp[81] you are declaring an array of chars that is
81 consecutive characters to which &temp[0] is the start of that array.
Code:

When you say textl[0] = temp , you are saying point the pointer at textl[0] to the start of the char array temp, infact, textl[0] = temp is just like saying
textl[0] = &temp[0].

Now when you DONT do that and you just say getline(textl[i], 81), you are saying, hey get 81 chars from the input stream and write them into the pointer textl[i].Now because your writing directly into a pointer, that at this stage is pointing nowhere or to some undefined place you get a segmentation fault.

If in your example you had allocated the memory in all of those pointers then you would have no problem, for example if you had put

Code:

for (int a = 0;a < 10 ;a++)
        {
        textl[a] = (char *)malloc(81);
        }


just before you try to read all those strings in then it would work.

Do you understand?

The above code will initialize all the pointers to hold 81 chars.
So when you then go getline(textl[i],81), the pointer your getline() function is writing into actually has somewhere to write to.
You not understanding why your getting a segmentation fault is due, to not understanding how the language works.
For example being able to tell what a statement like: char *bleh = "this is a string"
actually does is very important. Not knowing what is really going on here allows you to assume things like getline(textl[i], 81) shouldnt fail, i mean if i can assign a sentence into a pointer when i declare it, i should be able to read a string into a an un initialized pointer right? wrong!
For the above example when you write char *bleh = "some stuff", what happens is c declares some memory say enough to hold the string, which in this case is 10 chars, which you could do by calling malloc, memory allocation, like malloc(11), next it will fill 10 of those chars up with the string "some stuff", it will then use that last char to null terminate the string, that is the char '\0'. It then will send back a pointer to the first character in that array and assign the symbol bleh to it.

Code:

So you have a pointer to some memory that would be mapped out like this -> s o m e s t u f f \0, the pointer is pointing to
the first char 's'. When you call say this pointer to be printed out to the screen with say cout << bleh << endl, it will print stuff out until it reaches the null at the end \0.
Now malloc as its name suggests allocates memory. so malloc(23) will allocate 23 chars of memory and send back a void pointer.
So char *p = (char *)malloc(23) will allocate 23 chars like ( char men[23] ) and return back a void pointer which you then cast to a char * pointer and assign it to the symbol p.
Now you can reference all those chars like p[0] p[1] etc and assign chars into them like p[0] = 's' p[1] = 'o'.You must learn all of this and more, C and C++ are fantastic languages, but they deserve your undivided attention. Do you see why the guys above said what they did, because they cannot spend all this time to explain to you how the C language works, which is the only way to properly answer your question. Instead they are pointing you in the right direction to learn all this stuff yourself.

JMJ_coder 11-14-2007 03:18 PM

Hello,

I got the program working. Here is the final code:

Code:

#include <iostream>

int main()
{

  int i;
  char *textl[10];
  char *temp;

  for (i=0; i<10; i++){
    temp = new char [81];
    std::cout<<"Enter a line of text: ";
    std::cin.getline(temp, 81);
    textl[i] = temp;
  }


  for (i=0; i<10; i++){
    std::cout<<textl[i]<<std::endl;
  }

  return 0;
}

The key was the new command. I had tried this before I even posted the first time, but I added a delete command at the end of the loop that was defeating the purpose. I got rid of the delete and all is well.

Thanks for all your help.

JMJ_coder 11-14-2007 03:24 PM

Hello,

Quote:

Originally Posted by David1357 (Post 2957975)
Well, we do this for a living.

Hopefully, I will too after I complete my degree. :study:


Quote:

Originally Posted by David1357 (Post 2957975)
This is C/C++, not BASIC, so you have to do some heavy lifting. Look up the functions malloc, calloc, and free in your textbook. They will probably have some examples of what you are looking for.

You will also want to look at strcpy and memcpy. There is an important difference between the two.

My book doesn't even mention malloc, calloc, free or memcpy. I had to look them up on the internet to see what they were. The book does mention strcpy and I was thinking about it while I was creating the program.

I know it must be trying talking to a learning programmer like me, but I appreciate the help.

JMJ_coder 11-14-2007 03:29 PM

Hello,

Quote:

Originally Posted by genix (Post 2958052)
You said above that you 'assume', with a programming language like C/C++ you need to know. The best advice i can give you is, "learn the fundamentals"

I'm trying. I'm still working on my first programming class which teaches C++. That's the class the book is for (even though the professor doesn't really use it). The two MAJOR topics left to be learned in the semester are structures (which we began today) and classes. I agree, I want to learn the fundamentals, which is why I make it a point to do all the programming exercises in the book, even though the professor doesn't assign them (other than the first day, he hasn't mentioned the book).


Again, thanks for all the help.

genix 11-14-2007 05:19 PM

Ah its a pleasure to help a beginning programmer, IF, they listen to what you are saying. I recommend looking at all the stuff i wrote above, if you can re-read it you will see things like
Quote:

Once you understand pointers and like David said malloc and calloc, you can then move on to using C++'s new and delete.
;)

Here is an exercise for you, write me a post back, explaining WHY the 'new' works AND why this did NOT work

Code:

for (i=0; i<10; i++){
    std::cout<<"Enter a line of text: ";
    std::cin.getline(textl[i], 81);
  }


osor 11-14-2007 09:52 PM

Quote:

Originally Posted by JMJ_coder (Post 2958990)
I got the program working. Here is the final code:
<SNIP>

Not to burst your bubble, but have you tried your program out when an input string exceeds 81 characters in length?

genix 11-15-2007 02:10 AM

what you really want to be able to do is something like this
;)
functions.h
Code:

#ifndef FUNCTIONS_H
#define FUNCTIONS_H

char *getString();//function to get a string from stdin
char *resize(char *p, int size);//function to resize strings

#endif

function.c


Code:

#include "functions.h"
#include "stdlib.h"
#include "stdio.h"

#define STRSIZE 30

char *getString()
{
char *str = (char *)malloc(30);//start off with thirty, i mean, why not
char *start = str;
char c;
int size = STRSIZE;
int pos = 0;


        while ((c = getc(stdin))!= '\n' ){
                //test to see if we have enough room in our string
                if ( !(pos < size) ){
                        str = resize(str, size);
                        start = str;
                        str += size;
                }
        *str++ = c;
        }
        *str = '\0';
        return start;
}


char *resize(char *str, int size)
{
        int i;
        //create a new string thats STRSIZE bigger
        char *newstring = (char *)malloc(STRSIZE+size);
        //copy the data across
        for( i = 0;i < size;i++){
                newstring[i] = str[i];
        }
        free(str);
        return newstring;

}

main.c
Code:

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


int main(){


printf("%s\n", getString());


}


genix 11-15-2007 05:04 AM

OK this is my last post, here is the updated C++ version

function.h

Code:

#ifndef FUNCTION_H
#define FUNCTION_H

char *getString();
char *resize(char *p, int siza);


#endif

the implementation

function.cpp
Code:

#include "function.h"
#include <iostream>

        const int increment = 2;
        const char terminator_III = '\0';

char *getString()
{
        char c;
        char *str;
        int current_size = 0;
        int pos = 0;

        str = new char[increment];
        char *start = str;

        current_size = increment;

        while (( c = getc(stdin)) != '\n' )
        {
                if( !(pos < current_size))
                {
                        str = resize(start,current_size);
                        current_size += increment;
                        start = str;
                        str += pos;
                }
                *str++ = c;
                pos++;
        }

        //overwrite the new line with a null terminator III
        *str = terminator_III;
        //just a thought but might change stdin to something more portable
        return start;
       



}

char *resize(char *p, int size)
{
        //create a new string
        char *newstr = new char[size+increment];
        //copy the old string into the new string
        for(int i = 0;i < size;i++)
        {
                newstr[i] = p[i];
        }
        //delete []p;
        return newstr;

}

and the boring

main.cpp
Code:

#include "function.h"
#include <iostream>

using namespace std;


int main() {

char *pointers[10];


       

        for (int i = 0; i < 10;i++)
        {
        pointers[i] = getString();
        }

        for (int i = 0;i < 10;i++)
        {
                cout << pointers[i] << endl;
        }

}

There you go, i would have to say that my getString is far more
DYNAMIC than the actual C++ programming languages implementation of getline is.

To compile use

Code:

g++ -g -c function.cpp
g++ -g -c main.cpp
g++ -o app main.o function.o


David1357 11-15-2007 07:45 AM

Re: C'est horrible
 
Quote:

Originally Posted by genix (Post 2959468)
Code:

#define STRSIZE 30

char *getString()
{
char *str = (char *)malloc(30);//start off with thirty, i mean, why not


Why is "30" specified in the call to malloc instead of STRSIZE?
Where is the check for NULL in the return value from malloc? malloc can fail...


All times are GMT -5. The time now is 06:02 AM.