today i was trying to get friendly with char * string... but it seems im failing :)
Every time i call strcmp/strncmp/strcpy function my source gets corrupted...
here is the snippet
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student
{
int UID;
char name[20];
char surname[20];
};
char * getString(int minChars, int maxChars);
struct student * myStud;
int main(int argc, char** argv) {
myStud = (struct student*)malloc(sizeof(struct student));
while(1)
{
printf("\nEnter new name: ");
strcpy(myStud->name,getString(1,19));
printf("\n The values is now %s",myStud->name);
}
return (EXIT_SUCCESS);
}
char * getString(int minChars, int maxChars)
{
char string[maxChars+1];
scanAgain:
scanf("%s",&string);
if(strlen(string)<minChars)
{
printf("\nToo few symbols, try again: ");
goto scanAgain;
}
if(strlen(string)>maxChars)
{
printf("\nToo many symbols, try again: ");
goto scanAgain;
}
string[maxChars]='\0';
return(string);
}
Output:
Enter new name: Alekasdasd
The values is now Alekasda�#
Enter new name:
im just a beginner so it might be something very simple... might be not.
oh and by the way, using linux and netbeans as SDK, gcc as compiler.
You're returning a pointer to a stack variable.
char * getString(int minChars, int maxChars)
{
char string[maxChars+1];
When getString returns, string is invalid. Your return value points to this invalid string.
Use:
char * getString(int minChars, int maxChars, char * string) {
return string;
}
...
char string[100];
getString(1, 2, string);
Also, goto? Stop that please - use for, while do, do while but not goto
char * getString(int minChars, int maxChars)
{
char string[maxChars+1];
...
return(string);
}
The "string" array here is only allocated for the scope of the getString() function. Once it returns (goes out of scope), it ceases to exist and will be overwritten by the rest of your program. The "return(string)" statement returns the pointer of this data that's not allocated anymore -- not the data itself. This happens due to the implicit array-to-pointer conversion in C.
Instead of doing this, your getString() function should take a char* as an argument, which is allocated in the calling function.
I see two problems with your getString() function:
The string variable must be declared static so that the memory used for it is not released (stack, popped) when the function returns.
The parameter to scanf() you do not want the & token, but simply the pointer to the buffer, string.
That is, change the lines:
char string[maxChars+1];
scanf("%s",&string);
to read
static char string[maxChars+1];
scanf("%s",string);
The reason you do not want the ampersand in the scanf() call is the following from the man page, man 3 scanf:
s Matches a sequence of non-white-space characters; the next
pointer must be a **pointer to character array** that is long enough
to hold the input sequence and the terminating null character
('\0'), which is added automatically. The input string stops at
white space or at the maximum field width, whichever occurs
first.
240 lines is not a "snippet".
As James suggested in his comment, reduce the code to the minimum number of lines needed to reproduce the problem. At that stage the cause of the problem should become obvious to you -- if not try posting again.
Related
I'm a student and I m learning c (programming in ANSI c -> fifth edition) and facing the below error:
I'm implementing one program with typedef
In below c program give an error:
main.c:8:6: warning: ‘gets’ is deprecated [-Wdeprecated-declarations]
/usr/include/stdio.h:638:14: note: declared here
main.c:(.text+0x1f): warning: the `gets' function is dangerous and should not be used.
enter name:cara
Segmentation fault (core dumped)
program:
#include <stdio.h>
char * read(void); //here I m writing prototype but I don't know what is the prototype and why here write the prototype?
char * read(void)
{
char * name;
printf("enter name:");
gets(name); //get string input using gets(..) function
return name;
}
void main()
{
char * name;
name = read();
printf("welcome,%s\n",name);
}
above program is a complexity that is why I m using typedef in the below program:
this below program continuously run why?
#include <stdio.h>
typedef char * string;
string read(void);
string read(void)
{
string name;
printf("enter name:");
gets(name);
return name;
}
void main()
{
string name;
name = read();
printf("welcome,%s\n",name);
}
What I'm doing wrong?
There are a couple of things wrong with this. When you do char * name, you define name as a char pointer, but you don't actually allocate any space for the string to be stored. Hence, when you try to write values into that string, you're writing values in a random place that may not be writable or may contain crucial data that cannot be overwritten. Instead, try declaring name as char name[256]; to allocate enough space for it. Also, don't use gets, as it can lead to very, very, nasty things. Instead, use fgets to read input, and provide an upper limit on the number of characters equal to the amount of data you allocated. So, if you declared name as char name[256];, call fgets with fgets(name, 256, stdin);
The program has undefined behavior because you are using an uninitialized pointer that has an indeterminate value
char * name;
printf("enter name:");
gets(name);
You need to allocate memory where you are going to read a string.
As for the function gets then it is indeed an unsafe function and is not supported by the C Standard anymore. Use instead the standard C function fgets.
Pay attention to that according to the C Standard the function main without parameters shall be declared like
int main( void )
And using a typedef like this
typedef char * string;
is a bad idea. For example using this typedef name you are unable to declare a pointer to constant data like
const char *p;
because this declaration
const string p;
is not equivalent to the above declaration but means the following declaration
char * const p;
The program can look for example the following way
#include <stdio.h>
char * read( char *s, size_t n )
{
s[0] = '\0';
printf( "Enter name: " );
fgets( s, n, stdin );
return s;
}
int main( void )
{
enum { N = 100 };
char name[N];
printf( "%s", read( name, N ) );
}
Its output might look like
Enter name: rahul_
rahul_
Pay attention to that the function fgets can append the entered string with the new line character '\n'. To remove it you can use the following trick
#include <string.h>
//...
name[ strcspn( name, "\n" ) ] = '\0';
I can't figure out what causes this problem... appreciate any help!
I've tried a lot of codes for strlen but this one was the only one that I could implement with only 1 error. With this code, I'm trying to read a string from a file, break it in words separated by space, determinate the length and then print the word and the length to the user.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
FILE*arquivo;
char nuks[80];
char frase[80];
typedef struct node {
char palavra;
struct node* esquerda;
struct node* direita;
int altura;
} No;
size_t strlen(char *nstr)
{
int total=0;
char str[80];
strcpy(str, nstr);
total = strlen(str);
printf("|%s| is |%d|", str, total);
}
int main()
{
No* raiz = NULL;
arquivo=fopen("README.txt","r");
fgets(nuks, 79, arquivo);
printf("%s\n",nuks);
char *parte;
// Get the first word
parte = (char*)strtok(nuks, " ");
// Get the other words
while(parte != NULL){
strlen(parte);
printf("%s\n", parte);
parte = (char*)strtok(NULL, " ");
}
printf("\n\n");
system("pause");
return 0;
}
You are calling a function named strlen() into a function also named strlen(), which makes it recursive and, what is worse, infinitely recursive!
Besides that, you don't need to have a local copy of nstr into str just for determining its length.
Finally, is there any reason for not using the standard strlen() function declared in string.h?
size_t strlen(const char *) is already defined in <string.h>, therefore the conflict. You should choose another function name for your function.
1> The standard strlen is conflicting with local strlen. (Probably the conflict error is here )
2> The fuction is not properly coded, calling recursively itself without any exit point.
The first one can be ignored as local definition will overload the one in string.h
But the problem is in the function.
Note that in your code, you've included the C string library
#include <string.h>
which has the function
size_t strlen(const char *str)
that returns the length of the string passed into the function.
However, in your code, you try to overwrite the function
size_t strlen(char *nstr)
which causes confusion when C tries to compile your file. Try to use a different name for your function instead. For example:
/* This function prints the length of string */
void print_strlen(char *nstr) {
int total=0;
total = strlen(nstr);
printf("|%s| is |%d|", nstr, total);
}
Also, note that in your code, you defined
char str[80];
which then copies the input nstr to str.
This is ok so long as the length of the string doesn't exceed 79 (note that there is a null terminator '\0' for string). But as soon as the length of your string exceed that limit, your output will be a bit funny!
I'm trying to get input from the user while allocating it dynamically and then "split" it using strtok.
Main Questions:
Im getting an infinite loop of "a{\300_\377" and ",".
Why do i get a warning of "Implicitly declaring library function "malloc"/"realoc" with type void"
Other less important questions:
3.i want to break, if the input includes "-1", how do i check it? As you can see it breaks now if its 1.
4.In the getsWordsArray() i want to return a pointer to an array of strings. Since i dont know how many strings there are do i also need to dynamically allocate it like in the getInput(). (I dont know how many chars are there in each string)
int main(int argc, const char * argv[])
{
char input = getInput();
getWordsArray(&input);
}
char getInput()
{
char *data,*temp;
data=malloc(sizeof(char));
char c; /* c is the current character */
int i; /* i is the counter */
printf ("\n Enter chars and to finish push new line:\n");
for (i=0;;i++) {
c=getchar(); /* put input character into c */
if (c== '1') // need to find a way to change it to -1
break;
data[i]=c; /* put the character into the data array */
temp=realloc(data,(i+1)*sizeof(char)); /* give the pointer some memory */
if ( temp != NULL ) {
data=temp;
} else {
free(data);
printf("Error allocating memory!\n");
return 0 ;
}
}
printf("list is: %s\n",data); // for checking
return *data;
}
void getWordsArray(char *input)
{
char *token;
char *search = " ,";
token = strtok (input,search);
while (token != NULL ) {
printf("%s\n",token);
token = strtok(NULL,search);
}
}
EDIT:
i noticed i forgot to "strtok" command so i changed it to token = strtok(NULL,search);
I still get wierd output on the printf:
\327{\300_\377
Change:
int main(int argc, const char * argv[])
{
char input = getInput();
getWordsArray(&input);
}
to:
int main(int argc, const char * argv[])
{
char *input = getInput();
getWordsArray(input);
}
with a similar to the return value of getInput():
char *getInput()
{
// ...
return data;
}
In your code, you were only saving the first character of the input string, and then passing mostly garbage to getWordsArray().
For your malloc() question, man malloc starts with:
SYNOPSIS
#include <stdlib.h>
For your getchar() question, perhaps see I'm trying to understand getchar() != EOF, etc.
Joseph answered Q1.
Q2: malloc and realoc returns type void *. You need to explicitly convert that to char *. Try this:
data = (char *) malloc(sizeof(char));
Q3: 1 can be interpreted as one character. -1, while converting to characters, is equivalent to string "-1" which has character '-' and '1'. In order to check against -1, you need to use strcmp or strncmp to compare against the string "-1".
Q4: If you are going to return a different copy, yes, dynamically allocate memory is a good idea. Alternatively, you can put all pointers to each token into a data structure like a linked list for future reference. This way, you avoid making copies and just allow access to each token in the string.
Things that are wrong:
Strings in C are null-terminated. The %s argument to printf means "just keep printing characters until you hit a '\0'". Since you don't null-terminate data before printing it, printf is running off the end of data and just printing your heap (which happens to not contain any null bytes to stop it).
What headers did you #include? Missing <stdlib.h> is the most obvious reason for an implicit declaration of malloc.
getInput returns the first char of data by value. This is not what you want. (getWordsArray will never work. Also see 1.)
Suggestions:
Here's one idea for breaking on -1: if ((c == '1') && (data[i-1] == '-'))
To get an array of the strings you would indeed need a dynamic array of char *. You could either malloc a new string to copy each token that strtok returns, or just save each token directly as a pointer into input.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLINES 25
int get_lines(char *studentinfo[]);
int main()
{
int onswitch=0;
char *studentinfo[100];
char *fname[100];
char *lname[100];
char *score[100];
int counter;
int x,y;
char temp,temp2,temp3;
counter=get_lines(studentinfo);
for (y=0; y<counter; y++)
{
temp=strtok(studentinfo, " ");
fname[y]=malloc(strlen(temp));
strcpy(fname[y],temp);
temp2=strtok(NULL, " ");
lname[y]=malloc(strlen(temp2));
strcpy(lname[y],temp2);
temp3=strtok(NULL," ");
score[y]=malloc(strlen(temp3));
strcpy(score[y],temp3);
int get_lines(char *studentinfo[])
{
int n=0;
char buffer[80];
puts("Enter one line at a time; enter a blank when done.");
while ((n<MAXLINES) && (gets(buffer) !=0) && (buffer[0] != '\0'))
{
if ((studentinfo[n]=(char*)malloc(strlen(buffer)+1))==NULL)
return -1;
strcpy(studentinfo[n++],buffer);
}
return n;
}
Alright guys I am trying to make program that takes in student information for sorting later. I have taking the input down with the function on the bottom. I am trying to break down to the student information into three different pointers for sorting. The problem I am having is trying to allocate enough memory to store then information. Then actually storing the memory in that pointer location.
A simple input is
John Smith 80
^fname ^lname ^score
I thought the for loop I had would work in theory but it didnt (error: Unhandled exception at 0x0F3CFA50 (msvcr110d.dll) in ConsoleApplication3.exe: 0xC0000005: Access violation reading location 0xFFFFFF8) can anybody point me in the right direction (not just give me a loop that works) ?
With your implementation, you get an access violation. You are trying to touch a dirty region of memory. Here is the solution with an explanation below
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLINES 25
int get_lines(char *studentinfo[]);
int main()
{
int onswitch=0;
char *studentinfo[100];
char *fname[100];
char *lname[100];
char *score[100];
int counter;
int x,y;
char *temp,*temp2,*temp3;
counter=get_lines(studentinfo);
for (y=0; y<counter; y++)
{
temp=strtok(studentinfo[y], " ");
fname[y]=malloc(strlen(temp));
strcpy(fname[y],temp);
temp2=strtok(NULL, " ");
lname[y]=malloc(strlen(temp2));
strcpy(lname[y],temp2);
temp3=strtok(NULL," ");
score[y]=malloc(strlen(temp3));
strcpy(score[y],temp3);
printf("%s %s %s", fname[y], lname[y], score[y]);
}
}
int get_lines(char *studentinfo[])
{
int n=0;
char buffer[80];
puts("Enter one line at a time; enter a blank when done.");
while ((n<MAXLINES) && (gets(buffer) !=0) && (buffer[0] != '\0'))
{
if ((studentinfo[n]=(char*)malloc(strlen(buffer)+1))==NULL)
return -1;
strcpy(studentinfo[n++],buffer);
}
return n;
}
First off, you are missing an ending bracket } for your for loop as well as your main function. So add those.
Your getlines function is all good.
Your for loop is screwed up. In particular, you confused the data types you are passing. Remember, you have declared an array of POINTERS.
temp=strtok(studentinfo, " ");
This is saying, hey, let's tokenize my array pointer. You don't want this. You want to tokenize the yth element in that array! So element 0 in your array is a pointer to the string "JOHN SMITH 80". This is what we want to tokenize. Otherwise what you had was trying to tokenize somthing along the lines of 0xabcdabcd or whatever the memory address of the allocated array was.
temp=strtok(studentinfo[y], " ");
This is the correct way. It says tokenize the first element, which is a pointer to our string.
Your next problem is your temp variables. You are calling strlen(temp). strlen expects a pointer to a string. You are passing the data of the char itself. Actually, you are passing the return pointer (likely null) of the strtok function that was stored in your char byte.
char temp,temp2,temp3;
You declared three bytes for the type char. What you wanted was three char * to hold pointers to your string tokens.
char *temp,*temp2,*temp3;
With this, strlen takes in these pointers, mallocs some space for your fname elements, and then you proceed to copy into this element using strcpy.
Note: strcpy also takes two pointers, one for destination, one for source, so again your temp variables needed to be pointers to your strings.
Hope this helps let me know if you are confused with my explanation at all.
strcpy takes characters until it reaches a \0 character. You want to check out the strncpy or memcpy functions, and then manually add the null terminator.
I make this program ::
#include<stdio.h>
char *raw_input(char *msg);
main() {
char *s;
*s = *raw_input("Message Here Is: ");
printf("Return Done..");
printf(s);
}
char *raw_input(char *msg){
char *d;
printf("%s", msg);
scanf("%s",&d);
return d;
}
What this do is, it print my message and scan for input from the user, then print it,, but whats the problem in print the input from the user ???
Update::
I need the raw_input func. call be like this without any extra
*s = *raw_input("Message Here");
I dont want to use this ::
raw_input("Message Here Is: ", d);
....
Just want to return the string that the user will enter .
Update2::
from jamesdlin Answer( Thank You ),,Now its clear to my that's my problem was in how to return an allocated string in this :)
#include<stdio.h>
#define buffer 128
char *raw_input(char *msg);
main() {
char *s;
s = raw_input("Message Here Is: ");
printf("%s\n",s);
}
char *raw_input(char *msg){
char *d;
printf("%s", msg);
fflush(stdout);
fgets(d, buffer, stdin); ## In this there is a problem
return d;
}
now when i start this program its print the message and then just exit(end)the program without taking any word from the user ???
You don't allocate memory for d, so using it in scanf leads to undefined behaviour.
Actually, it's even worse than that: you pass the address of d to scanf, which is then filled with the integer read from console. In effect, you initialize a pointer with an integer value, so the pointer points to somewhere out in the jungle. Thus dereferencing it is undefined behaviour. [Update]: even this is not all: as #Heath pointed out below, this in fact allows you to corrupt your call stack by entering a sufficiently long input on the console :-((( [/Update]
Not to mention that you are trying to return a local variable from your function, which is destroyed as soon as it gets out of scope. This should work better:
void raw_input(char *msg, char *d);
main() {
char d[128];
raw_input("Message Here Is: ", d);
printf("Return Done..");
printf(d);
}
void raw_input(char *msg, char *d){
printf("%s", msg);
scanf("%s", d);
}
Fair enough, this does not prevent buffer overflow... but it is enough to ilustrate my point.
Update: so you want to return an allocated string (i.e. a char* pointer) from raw_input() in any case. AFAIK you have 3 choices:
return a pointer passed in by the caller as a parameter (a slight extension of my example above): this is the one I would prefer. However, this requires an extra function parameter (in fact 2, since we should also pass in the length of the buffer in a proper solution to avoid buffer overflows). So if you absolutely need to stick to the function signature shown above, this isn't an option.
return a pointer to a static / global buffer visible to both caller and callee: this is a variation of the above, to avoid modifying the function signature. The downside is that the code is more difficult to understand and maintain - you don't know that the function modifies a static / global variable without actually looking at its implementation. This in turn also makes unit testing more difficult.
return a pointer to a buffer allocated inside the function - although technically possible, this is the worst option, since you effectively pass on the ownership of the buffer; in other words, the caller must remember to free the buffer returned. In a simple program like the one you showed above, this may not seem like a big issue, but in a big program, that buffer may be passed around to far away places within the app, so there is a high risk that noone frees it in the end, thus leaking memory.
The pointer d in the function is uninitialized. scanf would be filling up arbitrary memory. Instead, you need to pass a buffer (character array) for it to fill, and the buffer has to be defined in main, otherwise it'll be destroyed before you can return it (unless you do dynamic allocation, but that's another story).
#include<stdio.h>
char *raw_input(char *msg);
int main() {
char *s;
s = raw_input("Message Here Is: ");
printf("Return Done..");
printf("%s", s);
free(s);
return 0;
}
char *raw_input(char *msg){
char *d;
d = malloc(20)
if(d==0) return 0;
printf("%s", msg);
scanf("%19s", d);
return d;
}
Try this, should work. The other answers pointed your errors out, as I can see... I was to slow ;)
EDIT: Ok, found an error... fixed it ;)
EDIT2:
Max suggested a struct was possible, here is some code:
#include<stdio.h>
struct mystring{
char str[20];
};
struct mystring raw_input(char *msg);
int main() {
struct mystring input;
input = raw_input("Message Here Is: ");
printf("Return Done..");
printf("%s", input.str);
return 0;
}
struct mystring raw_input(char *msg){
struct mystring input;
printf("%s", msg);
scanf("%19s", input.str);
return input;
}
As mentioned, you aren't allocating memory for use with scanf. But never ever use scanf; it's hard to use correctly and to avoid buffer overflows. Use fgets.
From the comp.lang.c FAQ: Why does everyone say not to use scanf? What should I use instead?
Also, while unrelated to your problem, this bit of code is dangerous:
*s = *raw_input("Message Here Is: ");
printf("Return Done..");
printf(s);
You are passing user-input directly to printf as a format strings, so this is susceptible to format string attacks if the printed string happens to include % characters. Better:
*s = *raw_input("Message Here Is: ");
printf("Return Done..");
printf("%s\n", s);
Also, you might want some newlines when you print. Also:
*s = *raw_input("Message Here Is: ");
won't work because s doesn't point to anything, so you're dereferencing a garbage pointer. Assuming that you fix raw_input to return an allocated string, it should be:
s = raw_input("Message Here Is: ");
Lastly (also unrelated to your problem):
char *raw_input(char *msg){
char *d;
printf("%s", msg);
scanf("%s",&d);
return d;
}
You should call fflush(stdout) after printing the prompt. See My program's prompts and intermediate output don't always show up on the screen, especially when I pipe the output through another program.
Try this experiment:
#include<stdio.h>
char *raw_input(char *msg);
main() {
char *s;
s = raw_input("Message Here Is: ");
printf("Return Done..");
printf(s);
}
char *raw_input(char *msg)
{
int value = 0;
char *d;
printf("%s", msg);
scanf("%s",&d);
if (value)
printf("value has become %08X\n", value);
return d;
}
Perform several experiements with input messages as long as: 3, 4, 5, 7, 8, 9, 11, 12, 13, etc. characters long. See what the result is for the integer variable value. You will see that due to your misuse of scanf() by passing the address of d, you are allowing scanf() to destroy local variables of your function, including the return address.
And that gets us back to the name of this web site.
You can not return a pointer of a variable that has been created inside the function. The variable d is not valid anymore in the main function.
try this:
1. create the variable d in the main function
2. and pass it to the raw_input function
void raw_input(char *msg, char *d)