I am having trouble with a function that should read a string from the user. I am always getting (null) as the output.
Is this even a "right" approach for that kind of problem?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int getString(char *input);
int main(void)
{
char *arr = NULL;
printf("please enter string: ");
getString(arr);
printf("%s", arr);
return 0;
}
int getString(char *input)
{
int i;
char c;
char *tmp;
input = malloc(sizeof(char));
for (i = 0; (c = getchar()) != EOF && c != '\n'; ++i) {
tmp = realloc(input, (i + 2) * sizeof(char));
if (tmp == NULL) {
free(input);
printf("allocation error");
return -1;
}
input = tmp;
input[i] = c;
}
input[i] = '\0';
return 0;
}
If you want to dynamically allocate the string you need to pass a pointer to char*, not just a char *. This way, the function can modify the real char * pointer and the caller will see the result. In your current code, the input variable only exists inside the function and does not affect the variable used by the caller, therefore your arr stays unchanged (NULL).
Something like this:
int getString(char **input)
{
int i;
char c;
char *tmp, *cur = NULL;
// No initial malloc() needed here.
// Let realloc() do the job passing NULL the first time.
for (i = 0; (c = getchar()) != EOF && c != '\n'; ++i) {
tmp = realloc(cur, (i + 2) * sizeof(char));
if (tmp == NULL) {
free(cur);
printf("allocation error");
return -1;
}
cur = tmp;
cur[i] = c;
}
cur[i] = '\0';
*input = cur;
return 0;
}
And then pass the parameter like this:
getString(&arr);
You should return the input pointer, since it is local to your function and get deallocated when the program leaves from the function, so in main the arr is still NULL.
int* getString(char *input);
int main(void)
{
//...
arr = getString(arr);
//...
}
int* getString(char *input)
{
//...
return input;
}
Related
I am trying to make a function that will allocate memory dynamically while the user hit any key other than ENTER. The code compiles without errors or warnings (on gcc) but is not working properly...could someone tell me what is going wrong exactly?
I got the code to work if I modify the function to return a pointer to char i,e, something like
char * getString(char * string);
However I am still curious about the original code and why is not working, would very much appreciate any explanation. Thanks in advance to anyone who takes the time to read this.
#include <stdio.h>
#include <stdlib.h>
void getString(char * string);
int main(void){
char * str = NULL;
printf("Write something:\n");
getString(str);
printf("You wrote:\n");
printf("%s\n", str);
free(str);
return 0;
}
void getString(char * string){
char ch;
int length = 0;
do{
scanf("%c", &ch);
if(length == 0){
string = (char *) malloc(sizeof(char));
} else {
string = (char *) realloc(string, (length + 1) * sizeof(char));
}
if(string == NULL){
printf("ERROR: memory could not be allocated!!\n");
}
string[length] = ch;
length++;
} while(ch != '\n');
string[length - 1] = '\0';
}
The string parameter is being passed in to getString() by value, so it is a copy of the str variable, and as such any changes that getString() makes to string itself, like assigning a memory address to it, are not reflected in the original str variable.
To fix this, you need to pass the string parameter by pointer instead.
You also need to fix the memory leak and access violation that your code has if realloc() fails.
Try this:
#include <stdio.h>
#include <stdlib.h>
void getString(char ** string);
int main(void){
char * str = NULL;
printf("Write something:\n");
getString(&str);
printf("You wrote:\n");
printf("%s\n", str);
free(str);
return 0;
}
void getString(char ** string){
char ch, *newstr;
int length = 0;
if (string == NULL) {
printf("ERROR: invalid parameter!!\n");
return;
}
*string = NULL;
do{
if (scanf("%c", &ch) < 1) {
ch = '\n';
}
newstr = (char *) realloc(*string, length + 1);
if (newstr == NULL){
printf("ERROR: memory could not be allocated!!\n");
free(*string);
*string = NULL;
return;
}
*string = newstr;
newstr[length] = ch;
length++;
}
while (ch != '\n');
(*string)[length - 1] = '\0';
}
A better way to implement your solution.
You should use double pointer as the argument of getString which is going to store the input string from the user.
#include <stdio.h>
#include <stdlib.h>
void getString(char**); // function prototype
/* Main function */
int main()
{
/* Pointer to point to the memory location
* where input string will be stored */
char *s=NULL;
/* Call by reference,the function will place
* string in memory location where the pointer
* is pointing */
getString(&s);
printf("s=%s\n",s);
free(s);
return 0;
}
/* getString function will
* store each input character in
* the allocated memory area. */
void getString(char** p)
{
if(*p==NULL){
if((*p=malloc(1*sizeof(char)))==NULL)
exit(0);
}
int c; //Variable to store each input character
size_t i=0; //Counter to keep track of the size of the input string
while((c=getchar())!='\n' && c!=EOF){
char* newp = realloc(*p,i+1);
if(newp==NULL){
fprintf(stderr,"realloc failed\n");
free(p);
exit(0);
}
*p = newp;
*(*p+i)=c;
i++;
}
*(*p+i)='\0'; //Null character to end the string.
}
I have problems with getstring. I do not know why it does not work, the output in the main function printf do not put nothing
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *getstring(unsigned int len_max)
{
char *linePtr = malloc(len_max + 1); // Reserve storage for "worst case."
if (linePtr == NULL) { return NULL; }
int c = 0;
unsigned int i = 0;
while (i < len_max && (c = getchar()) != '\n' && c != EOF){
*linePtr++ = (char)c;
i++;
}
*linePtr = '\0';
return linePtr;
}
int main()
{
char *line = getstring(10);
printf("%s", line);
free(line);
return 0;
}
The problem is that linePtr points to the end of the string containing the input line, not the beginning, because you do linePtr++ during the loop.
Instead of incrementing linePtr, use linePtr[i++] to store each character during the loop.
char *getstring(unsigned int len_max)
{
char *linePtr = malloc(len_max + 1); // Reserve storage for "worst case."
if (linePtr == NULL) { return NULL; }
int c = 0;
unsigned int i = 0;
while (i < len_max && (c = getchar()) != '\n' && c != EOF){
linePtr[i++] = (char)c;
}
linePtr[i] = '\0';
return linePtr;
}
If you really need to do it by incrementing a pointer, you need to save the original value of linePtr in another variable, and return that rather than the one that you increment.
your problem is that you are returning the end of your buffer, You need to keep a copy of linePtr or to index it. (You are incrementing it in your loop);
Hi I need some help with debugging my program: It should read from the Console, process the input and give it back out:
The error occures after while(scanf("%15s", input) != EOF) is called the 2nd time. Unfortunately I can't tell you what the error is, because the progam freezes and doesn't give me any Information. I think there is something wrong with the input var (it is passed multiple times)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
char* repeat(char c, int n);
char* drawLabel(char* label, int n);
char* drawBarnorm(char* label, int value);
char* drawBar(char* label, double value);
int main(void)
{
char* input;
double numIn;
char buf[] = "";
char* pOutput = &buf[0];
while(scanf("%15s", input) != EOF)
{
scanf("%lf", &numIn);
if (numIn > 1)
{
if (numIn > 30)
{
printf("num to big!\n");
return 0;
}
strcat(pOutput, drawBarnorm(input, (int)numIn));
} else
{strcat(pOutput, drawBar(input, numIn));}
printf("%s\n", pOutput);
}
printf("%s\n", pOutput);
return 0;
}
char* repeat(char c, int n)
{
char* out = (char*)malloc(sizeof(char)*50);
int i, len;
out[0] = '\0';
for (i = 0; i < n; ++i)
{
len = strlen(out);
out[len] = c;
out[len+1] = '\0';
}
return out;
}
char* drawLabel(char* label, int n)
{
if (strlen(label) > n)
{
char* newLabel = (char*)malloc(sizeof(char)*(n+1));
newLabel[0] = '\0';
strncpy(newLabel, label, n);
newLabel[n] = '\0';
return newLabel;
} else if (strlen(label) < n)
{
strcat(label, repeat(' ', n-strlen(label)));
}
return label;
}
char* drawBarnorm(char* label, int value)
{
char* bar = (char*)malloc(sizeof(char)*41);
char* barPart;
bar[0] = '\0';
bar = drawLabel(label, 8);
strcat(bar, "|");
barPart = drawLabel(repeat('#', value), 30);
strcat(bar, barPart);
strcat(bar, "|");
return bar;
}
char* drawBar(char* label, double value)
{
int val = (int)(30.0*value);
return drawBarnorm(label, val);
}
Thank you for helping me out with this.
char* input = malloc(size); /* Allocate memory of your wish */
Allocate memory to input You have not initialized your pointer.
The pointer should be pointing to some valid memory location to store the value through scanf()
You have to initialize input or declare it as an array like this
char input[16];
also, you should notice that scanf does not return EOF it returns the number of arguments matched, so you have to change
while(scanf("%15s", input) != EOF)
to
while(scanf("%15s", input) == 1)
because while(scanf("%15s", input) != EOF is always true.
I have to dynamically allocate a pointer inside a while.
char * allocationg_memory(char [] path p) {
char message[4000];
char c;
unsigned int i = 0;
unsigned int count;
FILE *f;
//open the file
f = fopen(p, "rt");
count = 0;
//copy the contain of the file in message
if (f) {
while ((c = getc(f)) != EOF) {
count++;
message[i] = c;
i++;
}
fclose(f);
}
//allocating the memory
char *str = (char *) malloc(sizeof (char) * (count));
if (str == NULL) {
printf("error allocating memory for string\n");
exit(1);
}
//copy the message
strncpy (str, message, count);
return str;
}
void main {
char * ptr;
do {
//my path dynamically changing
path = path_of_file;
ptr = allocating_memory(path);
printf("%s", ptr);
free(ptr);
} while (1);
}
If I set ptr = NULL it gives me segmentation fault, if I don't, if the next print is bigger than the previus, the 2nd is printed over the 1st. What's wrong with my code?
For starters:
Your initial allocation is for 0 bytes.
You are trying to print what you have allocated as if it were a string.
Your loop never ends.
This works for me. Hopefully it helps
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char * allocating_memory(int c) {
char *str = malloc ( c + 1); // allow an extra for the null
strncpy ( str, "abcdefghijklmnopqustuvwxyx", c);
str[c] = '\0'; // make sure the string is null terminated
return str;
}
int main () {
char * ptr;
int counter = 2;
do {
ptr = NULL;
ptr = allocating_memory(counter);
printf("%s\n", ptr);
free(ptr);
counter++;
} while (counter < 27);
return 0;
}
I have a structure
typedef struct store
{
char name[11];
int age;
} store;
and a main function(below is part of it):
int main()
{
int i=0;
int inputs;
char line[100];
char name[11];
char command[11];
store read[3000];
while(i < 3000 && gets(line) != NULL)
{
int tempage;
inputs = sscanf(line, "%10s %10s %d", command, name, &tempage);
if (inputs == 3)
{
if (strcmp(command, "register") == 0)
{
strncpy(read[i].name, name,10);
read[i].age = tempage;
i++;
....
I need to modify it so that it can read a line of arbitrary length, and store the name from the line which is also a string of arbitrary length using malloc and realloc.
How should I approach this?
What you need to do is read the line in smaller increments, and resize your buffer as you go.
As an example (not tested and not meaning to be particularly elegant, just an example):
char *readline(FILE *f)
{
char *buf = NULL;
size_t bufsz = 0, len = 0;
int keep_going = 1;
while (keep_going)
{
int c = fgetc(f);
if (c == EOF || c == '\n')
{
c = 0; // we'll add zero terminator
keep_going = 0; // and terminate the loop afterwards
}
if (bufsz == len)
{
// time to resize the buffer.
//
void *newbuf = NULL;
if (!buf)
{
bufsz = 512; // some arbitrary starting size.
newbuf = malloc(bufsz);
}
else
{
bufsz *= 2; // issue - ideally you'd check for overflow here.
newbuf = realloc(buf, bufsz);
}
if (!newbuf)
{
// Allocation failure. Free old buffer (if any) and bail.
//
free(buf);
buf = NULL;
break;
}
buf = newbuf;
}
buf[len++] = c;
}
return buf;
}
Change the name[11] to *name;
Allocate memory for that everytime using malloc.
By the way, register is a keyword in C language. You can't use it like you did !
I think what you're looking for is:
char* name;
name = (char*)malloc(sizeof(char));
This alternative approach is similar to #asveikau's, but economize on the use of malloc() by copying on the stack.
Please do not use this for homework answer.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
char * slurponeline(FILE *f, int s) {
const int size = 4096;
char buffer[size];
char * r;
int c,i=0;
while( i<size && (c = fgetc(f),c>=0 && c!='\n')) buffer[i++]=c;
if (0 == s && 0 == i) return 0;
r = (size==i)? slurponeline(f,s+size):malloc(s+i);
memcpy(r+s,buffer,i);
return r;
}
int main(int argc, char ** argv) {
FILE * f = fopen(argc>1?argv[1]:"a.out","rb");
char * a,*command,*commandend,*name,*nameend;
int age;
while (a = slurponeline(f,0)) {
char * p = a;
while (*p && *p == ' ') ++p; // skip blanks.
command = p;
while (*p && *p != ' ') ++p; // skip non-blanks.
commandend = p;
while (*p && *p == ' ') ++p; // skip blanks.
name = p;
while (*p && *p != ' ') ++p; // skip non-blanks.
nameend = p;
while (*p && *p == ' ') ++p; // skip blanks.
age = atoi(p);
*commandend=0;
*nameend=0;
printf("command: %s, name: %s, age: %d\n",command,name,age);
free(a);
}
}