Reputation: 23
I need some help regarding dynamic allocation of arrays of pointers in C. I am trying to create a program that reads a sentence of words from user input, and stores the words in character array strings. I then want to save the pointers char *word
to these words in an array of pointers char **wordArray
.
Creating a working method for dynamic allocation for the words was easy enough, and it reads character by character from user input. However, trying to adapt this method for the array of pointers was trickier.
The current function char **varArray
is obviously flawed, but my thinking was "while the user has input, get words pointers for the array of pointers". It now effectively loops the first word for every char c
.
My question is, how do I implement a second layer (char **varArray()
) of dynamic memory allocation of my array of pointers? How can the function detect when to call char *word()
?
Feedback for the code, style, or other errors are of course appreciated. My level is intermediate beginner.
/*CREATES AND ALLOCATES DYNAMIC VARIABLE ARRAY*/
#include <stdio.h>
#include <stdlib.h>
char **varArray();
char *word();
char **varArray()
{
char **tmp=NULL;
char **wordArray=NULL;
size_t size=0;
char c = EOF;
int words=0;
while(c) {
c=getc(stdin);
if (c == EOF || c == '\n')
c=0;
if (size <= words) {
size+=sizeof(char *);
tmp = realloc(wordArray,size);
if(tmp == NULL) {
free(wordArray);
wordArray=NULL;
printf("Memory allocation failed. Aborted.\n");
break;
}
wordArray=tmp;
}
words++;
wordArray[words]= word();
return wordArray;
}
The method for retrieving ONE word:
/*GETS ONE WORD FROM USER INPUT*/
char *word()
{
char *word=NULL, *tmp=NULL;
size_t size=0;
char c = EOF;
int letters=0;
while(c) { //reads character by character
c=getc(stdin);
if (c == EOF || c == '\n' || c==' ') //remove ' ' to read all input
c =0;
if (size <= letters) { //increase and reallocate memory
size = size + sizeof(char);
tmp = realloc(word,size);
if (tmp==NULL) { //check if allocation failed
free(word);
word=NULL;
printf("Memory allocation failed. Aborted.\n");
break;
}
word= tmp;
}
letters=letters+1;
word[letters]=c;
}
/*ADD SENTINEL CHARACTER*/
letters++;
size += sizeof(char);
word = realloc(word,size);
word[letters]='\n';
return word;
}
Upvotes: 2
Views: 765
Reputation: 23
I have now successfully implemented a version of the shell provided by @n.m. However, another problem arose - since word()
relies on the sentinel newline character \n
to quit, it also fails to read the final word, and does not enter the loop the last, vital time.
I have tried to implement some if-cases, but these of course fail due to the while-condition. Another idea would be to implement some switch case, but I am not sure that would avoid the nastiness of the while loop?
Do note that the code has little error checking to minimise the clutter.
char **wordArray() {
char *currentWord;
char **wordArray=NULL;
size_t size=0;
int i=0;
while((currentWord = word()) != NULL) {
size+=sizeof(char *);
wordArray=(char **) realloc(wordArray,size);
wordArray[i]=currentWord;
printf("Test - Current word: %s\n",currentWord);
i++;
}
return wordArray;
}
The relevant word()
function:
char *word() {
char ch;
int i=0;
size_t size=0;
char *returnWord = NULL;
char *outputWord = NULL;
char *tmp = NULL;
while((ch = getc(stdin)) != EOF && ch !='\n') { //&& ch !='\n'
if (ch != ' ' ) { //&& ch !='\n'
size += sizeof(char);
tmp = (char *) realloc(outputWord,size);
outputWord= tmp;
outputWord[i]=ch;
printf("Test1: %c\n",*(outputWord+i));
i++;
} else {
printf("Test2: %s\n",outputWord);
returnWord=outputWord;
outputWord=NULL;
printf("Test3: %s\n",returnWord);
return returnWord;
}
}
return NULL;
}
Upvotes: 0
Reputation: 119877
Here's the skeleton of the program you want to write.
...
char* currentWord;
char **wordArray=NULL;
while ((currentWord = word()) != NULL) {
.... add current word to word array with realloc...
}
....
char* word() {
int ch;
char* outputWord = NULL;
while ((ch = getch()) != EOF) {
if ( ... ch is a word character ... )
... add ch to output word with realloc ...
else {
char* ret = outputWord;
outputWord = NULL;
return ret;
}
}
return NULL;
}
Note how the two while
loops are doing exactly the same thing.
while ((element = getNextElement()) != sentinelValue) {
.... process newly obtained element ....
}
Upvotes: 1