Printing strings from 2D array using pointer to pointer - c

I am trying to build a program that uses dynamic allocation to build an array of strings.
After the user finishes to enter the words he wants into the array i want to print the array one word after the other. I am using pointers to pointers, however it doesn't seem to work:
#define SIZE 256
void paintWords(char **words, int count_words);
void main() {
char **words = NULL;
int flag = 1;
char buffer[SIZE];
int count_words = 0;
char *curr_word;
while (flag)
{
_flushall();
printf("Enter a word:");
gets(buffer);
words = (char**)realloc(words,++count_words*sizeof(char*));
curr_word = (char*)malloc(strlen(buffer) + 1);
words[count_words - 1] = curr_word;
printf("Do you wish to continue(0-no, 1-yes):");
scanf("%d", &flag);
}
paintWords(words, count_words);
}
void paintWords(char **words, int count_words) {
int j = 0;
for (int i = 0; i < count_words; i++)
{
printf("%s\n", words[i][j]);
}
}

Copy buffer to your malloc'ed block with strcpy
strcpy(curr_word, buffer);
you are discarding the read word since you don't put it anywhere
Don't use gets use fgets instead
fgets(buffer, sizeof(buffer), stdin);
this would prevent a buffer overflow.
This is just the jst which in your case is the 0th character of the word
printf("%s\n", words[i][j]);
change it to
printf("%s\n", words[i]);
turn compiler warnings on, it would tell you about printf expecting a char * and recieving char instead.
Also consider the following:
main() should return int.
You don't need to cast malloc.
Don't overwrite your pointer with realloc, use a temporary pointer and assign it to array on success only. Otherwise if realloc returns NULL you will not be able to free(array) for example.

++count_words
words = realloc(words,count_words*sizeof(char*));
words[count_words-1] = malloc(strlen(buffer) + 1);
strcpy(words[count_words-1],buffer);
Later print the array
printf("%s\n",words[i]);
realloc() can fail so
char *temp = realloc(words,count_words*sizeof(char*));
if(temp != NULL)
words = temp;
Few other fixes will be
You shouldn't be using gets which is no more a standard. Use fgets() and note that fgets() comes with a newline character
Check the code below:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 256
void paintWords(char **words, int count_words);
void main() {
char **words = NULL,ch;
int flag = 1;
char buffer[SIZE];
int count_words = 0;
//char *curr_word;
while (flag)
{
printf("Enter a word:");
fgets(buffer,sizeof(buffer),stdin);
words = (char**)realloc(words,++count_words*sizeof(char*));
words[count_words - 1] = (char*)malloc(strlen(buffer) + 1);
strcpy(words[count_words-1],buffer);
printf("Do you wish to continue(0-no, 1-yes):");
scanf("%d", &flag);
while((ch = getchar()) != '\n');
}
paintWords(words, count_words);
}
void paintWords(char **words, int count_words) {
int i;
for (i=0; i < count_words; i++)
{
printf("%s", words[i]);
}
}

Related

Array of pointers to char * in c using qsort

While adding string to my pointer's array, it is being overwriten by the last one. Could anyone tell me, where's my mistake?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main (){
int ile = 3;
const char * slowa[ile];
for(int j = 0; j < ile; j++){
char string[30];
gets(string);
slowa[j] = string;
printf ("%s dodalem pierwsza\n",string);
}
for (int i = 0; i < ile; i++) {
printf ("%s numer %d\n",slowa[i],i);
}
return 0;
}
The answer is in the following two lines of code:
char string[30];
...
slowa[j] = string;
The assignment sets slowa[j] to the address of the same buffer, without making a copy. Hence, the last thing that you put in the buffer would be referenced by all elements of slowa[] array, up to position of j-1.
In order to fix this problem, make copies before storing values in slowa. You can use non-standard strdup, or use malloc+strcpy:
char string[30];
gets(string);
slowa[j] = malloc(strlen(string)+1);
strcpy(slowa[j], string);
In both cases you need to call free on all elements of slowa[] array to which you have assigned values in order to avoid memory leaks.
You're always pointing to array of chars which is stack variable it's locally allocated only in scope of function, possibly each declaration of string will be on the same address as previous iteration in your loop. You could either instead of using array of chars allocate memory each loop iteration or use array and then using i.e strdup allocate memory for your new string like
slowa[j] = strdup(string) :
As others have said, you need to create copies of the strings, otherwise you set the strings to the same address, and therefore they just overwrite each other.
Additionally, I think using fgets over gets is a much safer approach. This is because gets is very prone to buffer overflow, whereas with fgets, you can easily check for buffer overflow.
This is some code I wrote a while ago which is similar to what you are trying to achieve:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PTRS 3
#define STRLEN 30
int
string_cmp(const void *a, const void *b) {
const char *str1 = *(const char**)a;
const char *str2 = *(const char**)b;
return strcmp(str1, str2);
}
int
main(void) {
char *strings[PTRS];
char string[STRLEN];
int str;
size_t len, i = 0;
while (i < PTRS) {
printf("Enter a string: ");
if (fgets(string, STRLEN, stdin) == NULL) {
fprintf(stderr, "%s\n", "Error reading string");
exit(EXIT_FAILURE);
}
len = strlen(string);
if (string[len-1] == '\n') {
string[len-1] = '\0';
} else {
break;
}
strings[i] = malloc(strlen(string)+1);
if (strings[i] == NULL) {
fprintf(stderr, "%s\n", "Cannot malloc string");
exit(EXIT_FAILURE);
}
strcpy(strings[i], string);
i++;
}
qsort(strings, i, sizeof(*strings), string_cmp);
printf("\nSuccessfully read strings(in sorted order):\n");
for (str = 0; str < i; str++) {
printf("strings[%d] = %s\n", str, strings[str]);
free(strings[str]);
strings[str] = NULL;
}
return 0;
}

String pointer in C prints weird symbol

I was having some difficulties when trying to print out the string pointer after dynamically insert a character at the front of char array.
The parameter *str is a dynamic char array from my main whereas the input is a single character which should append to the first element of the dynamic array after executing the insert().
int main(){
//code snippet. I removed other part to keep the question short
printf("How many characters do you want to input: ");
scanf("%d", &n);
str = malloc(n + 1);
printf("Input the string class: ");
scanf("%s", str);
//switch statement
case '1':
printf("What is the character you want to insert: ");
scanf(" %c", &input);
insert(&str, input);
break;
}
return 0;
}
void insert(char *str, char input) {
char *new_str;
int i, len = strlen(str);
new_str = malloc(len + 1);
new_str[0] = input;
strncpy(&new_str[1], str, len - 1);
new_str[len] = 0;
for (i = 0; i < len; i++) {
printf("%c", new_str[i]);
}
}
When I tried to loop thru the new_str and print out the string array, it gives me weird symbols and I have no idea what are they. Any ideas?
EDIT
The expected output as below:
How many characters do you want to input: 5
Input the string:datas
The string is: datas
Do you want to 1-insert or 2-remove or 3-quit?: 1
What is the character you want to insert: a
Resulting string: adata
The output I am getting:
Alternative version, avoiding any string copy functions. (Since, alter the strlen() you already know the string length to copy, you don't need any more string functions)
char * insert_a_character(char * str, char ch)
{
char * new;
size_t len;
if (!str) return NULL;
len = strlen(str);
new = malloc (1+len+1);
if (!new) retun NULL;
new[0] = ch;
memcpy(new+1, str, len);
new[len+1] = 0;
return new;
}
I assume that the caller will free if required for orig
char * insert(char *orig, char input) {
char * new_str = malloc(strlen(orig) + 2); // An extra one for null
strcpy(new_str + 1, orig);
new_str[0] = input;
printf("%s", new_str); // To print it out
return new_str; // The caller needs to free this;
}
That should work.
Assembling all comments:
void insert(char *str, char input) {
char *new_str;
int i, len = strlen(str);
new_str = malloc(len + 2);
new_str[0] = input;
strcpy(new_str+1, str);
new_str[len+1] = 0;
for (i = 0; i <= len; i++) {
printf("%c", new_str[i]);
}
}
Of course you still need to do something with the new string, such as returning it or freeing it.

How to dynamically allocate a string using function?

I am trying to allocate a dynamic string by accepting it from user. I want to do it using a function. I am trying to implement the following code, but it is not working properly.
#include<stdio.h>
#include<stdlib.h>
int string(char *str)
{
char c;
int i=0,j=1;
str = (char*)malloc(sizeof(char));
printf("Enter String : ");
while(c!='\n')
{
c = getc(stdin); //read the input from keyboard standard input
//re-allocate (resize) memory for character read to be stored
*str = (char*)realloc(str,j*sizeof(char));
*str[i] = c; //store read character by making pointer point to c
i++;
j++;
}
str[i]='\0'; //at the end append null character to mark end of string
printf("\nThe entered string is : %s",str);
return j;
}
int main()
{
int len;
char *str=NULL;
len=string(str);
printf("\nThe entered string is : %s and it is of %d length.",str,len);
free(str);
return 0;
}
A number of issues:
memory size is one too small.
while(c!='\n') first test c even though it is uninitialized.
string() should pass the address of a char * as in string(char **)
Better to use size_t rather than int when working with strlen().
Minor:
EOF is not detected. Use int c rather than char c to aid in detection.
Certainly inefficient to realloc() each loop.
Casting of malloc()/realloc() unnecessary.
Good to check for out-of-memory.
Use int main(void) rather than int main() for portability.
size_t string(char **str) {
assert(str);
int c;
size_t i = 0;
size_t size = 0;
*str = NULL;
printf("Enter String : ");
while((c = getc(stdin)) !='\n' && c != EOF) {
if (i == size) {
size *= 2 + 1; // double the size each time
*str = realloc(*str, size);
assert(*str);
}
(*str)[i] = c; // store read character by making pointer point to c
i++;
}
*str = realloc(*str, i+1); // right-size the string
assert(*str);
(*str)[i] = '\0'; // at the end append null character to mark end
printf("\nThe entered string is : %s",*str);
return i;
}
You need to pass a referejce to a pointer (int string(char **str)) because you're changing the value of str inside the function.
In main you should call string(&str)

Storing the buffer of fgets in Array

I'm new to C (coming from Java) and naturally that poses some difficulties. I would like to write just a short program that reads in char-Arrays from stdin and stores the individual strings in an array. After reading in the strings I just want to have them printed out, but that's when it gets really confusing for me.
Here's my code:
#include <stdlib.h>
#include <stdio.h>
int main(){
char **stringarray[2];
char buffer[5];
int i = 0;
while( i < 2 && fgets(buffer, 5, stdin) != NULL){
char *tmp = buffer;
stringarray[i] = &tmp;
i++;
}
for(int i = 0; i < 2; i++){
printf("%s\n", &stringarray[i]);
}
return 0;
}
The first part does in fact compiles (i.e. the part before the print out). I understand that my stringArray has to be an array of char pointers, because that's what a char array basically is in c. It's a pointer to the first character. At first I just wrote
while( i < 2 && fgets(buffer, 5, stdin) != NULL){
stringarray[i] = buffer;
i++;
}
which also compiled, but of course then I have one pointer that points to buffer, which will only save the last string that has been read.
What do I have to do that I can store a simple array of strings?
I suggest you change your code as following.
#include <stdlib.h>
#include <stdio.h>
#include <string.h> /* to use strdup function */
int main(){
char *stringarray[2]; /* I don't understand why you use pointer to pointer than pointer, char **stringarray[2]; */
char buffer[6]; /* I suggest 6 than 5, because string has terminate byte in C */
int i = 0;
while( i < 2 && fgets(buffer, 5, stdin) != NULL){
stringarray[i] = strndup(buffer, 5);
i++;
}
for(int i = 0; i < 2; i++){
printf("%s\n", stringarray[i]); /* changed stringarray */
}
return 0;
}
char **stringarray[2]; is like char ***stringarray because an array is like a pointer to the first value of the array.
printf wants a char* and &stringarray[i] is a char**
if a string is an array then an array of strings is an array of array.
So the code is :
int main()
{
char stringarray[2][5];//array of (array of char)
char buffer[5];
int i = 0;
while( i < 2 && fgets(buffer, 5, stdin) != NULL)
{
strcpy(stringarray[i],buffer); //copies the buffer into the string array
i++;
}
for(i = 0; i < 2; i++)
{
printf("%s\n", stringarray[i]);
}
return 0;
}
If you didn't want to use buffer you could just writte :
while( i < 2 && fgets(stringarray[i], 5, stdin) != NULL)
{
i++;
}
Note that you get 5 characters, the last one will be the NUL terminator \0. And because you have to press enter to validate, the one before \0 will be Line Feed\n. And you will only have 3 characters you really wanted.
You can do it using dynamic allocation technique as below .
#include<stdio.h>
#include<malloc.h>
#include <stdlib.h>
int main()
{
int num;
int len=0;
int i;
printf("Enter the number of elements to be entered ");
scanf("%d",&num);
//Allocate memory for the array of strings
char **var=(char **)malloc(num * sizeof(char *));
for(i=0;i<num;i++)
{
printf("Enter the string : ");
//get strings using getline
getline(&var[i],&len,stdin);
}
for(i=0;i<num;i++)
{
printf("String %d : %s \n",i,var[i]);
}
free(var);
}

C - Loop won't break

I want the loop to break when "Enter" is pressed. Any suggestions?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define len 20
#define limit 100
//Prototypes for functions
int read_word(char str[], int n);
int main(void)
{
char *p;
char word[len+1];
int i=0, nwords = 0;
//Loop for reading in words and allocating an array
for (;;)
{
if (nwords == limit)
{
printf("Insufficient Space\n");
break;
}
printf("Enter word: ");
scanf("%c", &word);
p = (char*) malloc(nwords*sizeof(char));
p[i]= read_word(word, len);
i++;
if (p == NULL)
{
printf("Insufficient Space\n");
break;
}
}
for(i=0; i<nwords; i++)
printf(" %s\n", p[i]);
return 0;
}
int read_word(char str[], int n)
{
char ch;
int i = 0;
while((ch = getchar()) != '\n')
if (i<n)
str[i++] = ch;
str[i] = '\0';
return i;
}
Your scanf call reads the first character, and then your read_word function overwrites it. If the scanf call reads the newline, it will then be ignored.
The lines:
p = (char*) malloc(nwords*sizeof(char));
p[i]= read_word(word, len);
... also appears wrong. read_word returns an integer (the length of the string read), but you are storing into a char array. Also, you are re-allocating the memory for p each time through the loop, so the values stored previously will be lost.
To fix:
change p to be an int *, and initialize it to null
change the malloc call to a suitable realloc
remove the call to scanf entirely
move the check for p == null before the assignment of `p = (char*) malloc(nwords*sizeof(char));'
Or: is p meant to actually be an array of strings (the words themselves) rather than the word length? In that case you have to:
change p to be an char **
change the allocation size (for the realloc call) to nwords * sizeof(*p)
allocate (using malloc) storage for each word instead of having word be a stack-allocated array
set p[i] = word; rather than the current assignment.

Resources