LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-13-2007, 09:41 AM   #1
JMJ_coder
Member
 
Registered: Apr 2006
Distribution: Fedora
Posts: 478

Rep: Reputation: 30
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.
 
Old 11-13-2007, 10:49 AM   #2
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,302
Blog Entries: 1

Rep: Reputation: 107Reputation: 107
Re: Pointer Arrays

Quote:
Originally Posted by JMJ_coder View Post
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.
 
Old 11-13-2007, 12:34 PM   #3
JMJ_coder
Member
 
Registered: Apr 2006
Distribution: Fedora
Posts: 478

Original Poster
Rep: Reputation: 30
Hello,

Quote:
Originally Posted by David1357 View Post
You should start by looking more closely at this line.
That is how the book says to declare it.
 
Old 11-13-2007, 02:34 PM   #4
PAix
Member
 
Registered: Jul 2007
Location: United Kingdom, W Mids
Distribution: SUSE 11.0 as of Nov 2008
Posts: 195

Rep: Reputation: 40
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

Last edited by PAix; 11-13-2007 at 02:36 PM. Reason: sorting my bad grammer
 
Old 11-13-2007, 03:24 PM   #5
JMJ_coder
Member
 
Registered: Apr 2006
Distribution: Fedora
Posts: 478

Original Poster
Rep: Reputation: 30
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.
 
Old 11-13-2007, 05:47 PM   #6
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,302
Blog Entries: 1

Rep: Reputation: 107Reputation: 107
Quote:
Originally Posted by JMJ_coder View Post
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.
Well, we do this for a living.

Quote:
Originally Posted by JMJ_coder View Post
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.

Last edited by David1357; 11-13-2007 at 05:48 PM. Reason: Added mention of strcpy and memcpy
 
Old 11-13-2007, 07:19 PM   #7
genix
LQ Newbie
 
Registered: Jul 2007
Distribution: slackware
Posts: 23

Rep: Reputation: 15
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.

Last edited by genix; 11-13-2007 at 11:25 PM.
 
Old 11-14-2007, 03:18 PM   #8
JMJ_coder
Member
 
Registered: Apr 2006
Distribution: Fedora
Posts: 478

Original Poster
Rep: Reputation: 30
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.
 
Old 11-14-2007, 03:24 PM   #9
JMJ_coder
Member
 
Registered: Apr 2006
Distribution: Fedora
Posts: 478

Original Poster
Rep: Reputation: 30
Hello,

Quote:
Originally Posted by David1357 View Post
Well, we do this for a living.
Hopefully, I will too after I complete my degree.


Quote:
Originally Posted by David1357 View Post
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.
 
Old 11-14-2007, 03:29 PM   #10
JMJ_coder
Member
 
Registered: Apr 2006
Distribution: Fedora
Posts: 478

Original Poster
Rep: Reputation: 30
Hello,

Quote:
Originally Posted by genix View Post
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.
 
Old 11-14-2007, 05:19 PM   #11
genix
LQ Newbie
 
Registered: Jul 2007
Distribution: slackware
Posts: 23

Rep: Reputation: 15
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);
  }

Last edited by genix; 11-14-2007 at 06:45 PM.
 
Old 11-14-2007, 09:52 PM   #12
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
Quote:
Originally Posted by JMJ_coder View Post
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?
 
Old 11-15-2007, 02:10 AM   #13
genix
LQ Newbie
 
Registered: Jul 2007
Distribution: slackware
Posts: 23

Rep: Reputation: 15
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());


}

Last edited by genix; 11-15-2007 at 02:14 AM.
 
Old 11-15-2007, 05:04 AM   #14
genix
LQ Newbie
 
Registered: Jul 2007
Distribution: slackware
Posts: 23

Rep: Reputation: 15
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

Last edited by genix; 11-15-2007 at 05:29 AM.
 
Old 11-15-2007, 07:45 AM   #15
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,302
Blog Entries: 1

Rep: Reputation: 107Reputation: 107
Re: C'est horrible

Quote:
Originally Posted by genix View Post
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...
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Question about outputing arrays with pointers, then just arrays... RHLinuxGUY Programming 1 04-12-2006 05:40 AM
pass pointer,, return pointer??? blizunt7 Programming 3 07-23-2005 01:36 PM
returning data to main() via a pointer to a pointer. slzckboy Programming 3 05-30-2005 01:20 PM
hot to set value of pointer to pointer to a structure in C alix123 Programming 2 11-17-2004 06:40 AM
pointer to pointer question in c lawkh Programming 2 01-29-2004 10:26 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:56 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration