C - Loop won't break - c

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.

Related

Dynamically create array in C taking in 1 character at a time

I am given an assignment to take in and store a string using a function, however, I am given some restrictions.
Only able to use getchar() to take in user input character by character
No assumption of length of the input (Not allowed to create a array of size 100 for example)
Not allowed to read the input twice, for example, using the first round of input to count string size and then ask the user to input again after creating an array of the string's size that was counted on the first round.
Not allowed to create a large buffer so a constant size buffer means memory will be wasted if the input is 1 character for example
int read_string()
{
char* input;
int counter = 0;
while (( input = getchar()) != '\n') //read until detect '\n'
{
printf("%c\n",input);
counter = counter + 1;
}
printf("Length of string: %d\n", counter);
}
I currently have no idea how to store character by character and dynamically resize an "array" like vectors equivalent in C++. C does not have vectors based on my research.
Based on my code now, when i type in "Hello",
the output will be
h
e
l
l
o
but I do not know how to store each character in a dynamic array
You'd have to use the realloc function, if you want to dynamically increase the size with every new character that you read.
When you use realloc, the content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved to a new location. If the function fails to allocate the requested block of memory, a null pointer is returned.
For every character that I read, I increment buffsize, but I do allocate buffsize + 1. Why? Because I need one extra position for the NULL terminator.
The last free position for a letter would be buffsize - 1 in this case and the last one will be assigned at the end of the while loop.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t buffsize = 0;
char *buffer = NULL;
char *temp;
char input;
while ((input = getchar()) != '\n') {
printf("%c\n", input);
/* Incraese the size & realloc */
++buffsize;
temp = realloc(buffer, (buffsize + 1) * sizeof(char));
if (!temp) {
printf("Error reallocating buffer!\n");
exit(1);
}
/* Setting the new read char */
buffer = temp;
buffer[buffsize - 1] = input;
}
if (buffsize) {
buffer[buffsize] = '\0';
printf("Result = [%s]\n", buffer);
} else {
printf("Empty input!\n");
}
printf("String size=%lu\n", buffsize);
/* Clean */
free(buffer);
return 0;
}
A bit more generic - function which adds a char to the string. Initially pointer should be NULL and it will take it into account automatically
char *addchar(char **str, int c)
{
size_t len= 0;
char *tmp;
if(*str)
{
len = strlen(*str);
}
tmp = realloc(*str, len + 2);
if(tmp)
{
*str = tmp;
tmp[len] = c;
tmp[len + 1] = 0;
}
return tmp;
}
and usage - a bit different than yours
int main()
{
char *mystring = NULL;
int input;
while (( input = getchar()) != EOF)
{
if(input == '\n' || input == '\r') continue;
if(!addchar(&mystring, input))
{
printf("\nMemory allocation error\n");
}
else
{
printf("String length %zu\n", strlen(mystring));
}
}
}
First off, the function getchar() returns and int not char * so you should not assign its return value to the pointer input declared in your code as char* input;
You should start by declaring an int variable; could be called len ; and initialize it with the value of 0. Next you should call the function malloc() and feed it 1 to allocate 1 byte of memory to hold a single character, and assign its return value to the pointer input, like the following:
int len = 0;
input = malloc(1);
Then you should store the NUL-terminating character '\0' in the allocated memory:
input[0] = '\0';
Then you create an int variable since the return value of getchar() is int. This variable which could be called ch shall store the user input.
Then you increase the size of your allocated storage to accommodate the new character:
input = realloc(input, len + 1);
input[len] = ch;
len++;
The entire code should look like the following:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int len = 0;
char *input = malloc(1);
input[0] = '\0';
int ch;
while ((ch = getchar()) != '\n')
{
input = realloc(input, len + 1);
input[len] = ch;
len++;
}
input[len] = '\0';
printf("You entered: %s\n", input);
printf("Length of str: %d\n", len);
free(input);
return 0;
}

Create variable numbers of string variables according to users's input(C language)

I would like to create an array of string variables, and the number of elements is depends on the user's input. For example, if the user's input is 3, then he can input 3 strings. Let's say "aaa", "bbb" and "ccc". They are stored by the same pointer to char(*ptr) but with different index.
code:
int main()
{
int t;
scanf("%d", &t);
getchar();
char *ptr = malloc(t*sizeof(char));
int i;
for(i=0;i<t;i++)
{
gets(*(ptr[i]));
}
for(i=0;i<t;i++)
{
puts(*(ptr[i]));
}
return 0;
}
t is the number of elements, *ptr is the pointer to array. I would like to store "aaa", "bbb" and "ccc" in ptr[0], ptr[1] and ptr[2]. However, errors have been found in gets and puts statement and i am not able to work out a solution. Would someone give a help to me? Thank you!
You shouldn't use gets(), which has unavoidable risk of buffer overrun, deprecated in C99 and deleted from C11.
Only one character can be stored in char. If the maximum length of strings to be inputted is fixed, you can allocate an array whose elements are arrays of char. Otherwise, you should use an array of char*.
Try this (this is for former case):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* the maximum length of strings to be read */
#define STRING_MAX 8
int main(void)
{
int t;
if (scanf("%d", &t) != 1)
{
fputs("read t error\n", stderr);
return 1;
}
getchar();
/* +2 for newline and terminating null-character */
char (*ptr)[STRING_MAX + 2] = malloc(t*sizeof(char[STRING_MAX + 2]));
if (ptr == NULL)
{
perror("malloc");
return 1;
}
int i;
for(i=0;i<t;i++)
{
if (fgets(ptr[i], sizeof(ptr[i]), stdin) == NULL)
{
fprintf(stderr, "read ptr[%d] error\n", i);
return 1;
}
/* remove newline character */
char *lf;
if ((lf = strchr(ptr[i], '\n')) != NULL) *lf = '\0';
}
for(i=0;i<t;i++)
{
puts(ptr[i]);
}
free(ptr);
return 0;
}
You can use this code which is given below because string array is like char 2D array so use can use pointer of pointer and when you allocate memory at run time by malloc then you need to cast into pointer to pointer char type.
int main()
{
int t;
scanf("%d", &t);
char **ptr = (char **)malloc(t*sizeof(char));
int i,j;
for( i=0;i<t;i++)
{
scanf("%s",ptr[i]);
}
for(i=0;i<t;i++)
{
puts(ptr[i]);
}
return 0;
}
Here is an example, of a clean if slightly memory inefficient way to handle this. A more memory efficient solution would use one string of MAX_LINE_LENGTH and copy to strings of precise lengths.. which is why one contiguous block of memory for the strings is a bad idea.
The asserts also just demonstrate where real checks are needed as malloc is allowed to fail in production where asserts do nothing.
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#define MAX_LINE_LENGTH 2048
int
main(void) {
int tot, i;
char **strheads; /* A pointer to the start of the char pointers */
if (scanf("%d\n", &tot) < 1)
return (1);
strheads = malloc(tot * sizeof (char *));
assert(strheads != NULL);
/* now we have our series of n pointers to chars,
but nowhere allocated to put the char strings themselves. */
for (i = 0; i < tot; i++) {
strheads[i] = malloc(sizeof (char *) * MAX_LINE_LENGTH);
assert(strheads[i] != NULL);
/* now we have a place to put the i'th string,
pointed to by pointer strheads[i] */
(void) fgets(strheads[i], MAX_LINE_LENGTH, stdin);
}
(void) printf("back at ya:\n");
for (i = 0; i < tot; i++) {
fputs(strheads[i], stdout);
free(strheads[i]); /* goodbye, i'th string */
}
free(strheads); /* goodbye, char pointers [0...tot] */
return (0);
}

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)

Printing strings from 2D array using pointer to pointer

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]);
}
}

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);
}

Resources