I'm new to C and i would like to learn something that is troubling me.
I have a code where i used strtok and basically it gets a string with the _#_ and seperates it from the string leaving the rest into chars and ints(i used atoi for that)
The program runs fine when i enter something like that: hello_#_2001_#_name_#_HARRY it gives me back hello,2001,name and HARRY. But when I input only hello_#_ it continues to run though stops doing anything. I think i need to assign a certain pointer to the first NULL but not sure if what i think is correct could you please help?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *split(char words[99])
{
int i;
char *word=strtok(words, "_#_");
char *year=strtok(NULL, "_#_");; // assigning NULL for previousely where it left off
char *definition=strtok(NULL,"_#_");
char *synonyms=strtok(NULL,"_#_");
i=atoi(year);
printf("%s\n", word);
printf("%i\n",i);
printf("%s\n", definition);
printf("%s\n", synonyms);
return 0;
}
int main()
{
char words[100];
printf("Enter a string\n");
scanf("%s", words);
split(words);
}
When I run your program and enter the string hello_#_, it throws a segfault when atoi is called. This is expected since year, definition, and synonyms will all be NULL. So you should check year for a NULL value before calling atoi.
From the man page:
The strtok() and strtok_r() functions return a pointer to the beginning of each subsequent token in the string, after replacing the token itself with a NUL character. When no more tokens remain, a null pointer is returned.
Try checking if the return value of strtok() is NULL before continuing.
You need to do some error checking. If you run out of tokens, strtok returns NULL, and then if you try to actually do something with that non-existing string (like pass it to atoi or try to print it) Bad Things will happen. It's up to you to decide what your function should do in that case (abort? Print what it can?) but you'll have to do something.
Related
Why does it print out the new word minus the first character when i printf("%s\n",array[0]) and not "Hello". Any tips for how to do solve that ?
Thanks in advance !
#include <stdio.h>
#include <string.h>
int main()
{
char newword;
char array[100][20]={
{'H','e','l','l','o'},
{'W','o','r','l','d'},
};
printf("%s\n",array[0]);
printf("%s\n",array[1]);
printf("Type a new word: ");
scanf("%s",&newword);
strcpy(array[1],&newword);
printf("%s\n",array[0]);
printf("%s\n",array[1]);
return 0;
}
Of course newword is not capable of holding a string (except the empty string) since it's just a single character, not an array. Using that with scanf() like you do is undefined behavior.
Make it:
char newword[20];
for instance, and preferably also scanf(" %19s", newword);, and check that scanf() succeeded.
Your code char newword; ... scanf("%s",&newword) yields undefined behaviour; you read in a string into a variable holding a single character; From that point on, all bets are off.
Write char newword[100]; ... and things should do better.
Ok, so I understand that strtok modifies its input argument, but in this case, it's collapsing down the input string into only the first token. Why is this happening, and what can I do to fix it? (Please note, I'm not talking about the variable "temp", which should be the first token, but rather the variable "input", which after one call to strtok becomes "this")
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
char input[]="this is a test of the tokenizor seven";
char * temp;
temp=strtok(input," ");
printf("input: %s\n", input); //input is now just "this"
}
When strtok() finds a token, it changes the character immediately after the token into a \0, and then returns a pointer to the token. The next time you call it with a NULL argument, it starts looking after the separators that terminated the first token -- i.e., after the \0, and possibly further along.
Now, the original pointer to the beginning of the string still points to the beginning of the string, but the first token is now \0-terminated -- i.e., printf() thinks the end of the token is the end of the string. The rest of the data is still there, but that \0 stops printf() from showing it. If you used a for-loop to walk over the original input string up to the original number of characters, you'd find the data is all still there.
You should printout the token that you receive from strtok and not worry about the input array because NULLs will be inserted by strtok. You need repeated calls to get all of the tokens:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
char input[]="this is a test of the tokenizor seven";
char * temp;
temp=strtok(input," ");
while( temp != NULL ) {
printf("temp is \"%s\"\n", temp );
temp = strtok( NULL, " ");
}
}
It's because strtok inserts nulls into each separator, which is why you use repeated calls to strtok to get each token. The input string cannot be used once you start using strtok. You don't "fix" it -- this is how it works.
I expected to get errors in following code, but I did not. I did not use & sign. Also I am editing array of chars.
#include <stdio.h>
int main()
{
char name[10] ="yasser";
printf("%s\n",name);
// there is no error ,
// trying to edit array of chars,
// also did not use & sign.
scanf("%s",name);
// did not use strcpy function also.
printf("%s\n",name);
return 0;
}
I expected to get errors in following code, but I did not.I did not use & sign.
scanf("%s",name);
That's totally ok as name is already the address of the character array.
It sounds like you have several questions:
calling scanf("%s", name) should have given an error, since %s expects a pointer and name is an array? But as others have explained, when you use an array in an expression like this, what you always get (automatically) is a pointer to the array's first element, just as if you had written scanf("%s", &name[0]).
Having scanf write into name should have given an error, since name was initialized with a string constant? Well, that's how it was initialized, but name really is an array, so you're free to write to it (as long as you don't write more than 10 characters into it, of course). See more on this below.
Characters got copied around, even though you didn't call strcpy? No real surprise, there. Again, scanf just wrote into your array.
Let's take a slightly closer look at what you did write, and what you didn't write.
When you declare and initialize an array of char, it's completely different than when you declare and initialize a pointer to char. When you wrote
char name[10] = "yasser";
what the compiler did for you was sort of as if you had written
char name[10];
strcpy(name, "yasser");
That is, the compiler arranges to initialize the contents of the array with the characters from the string constant, but what you get is an ordinary, writable array (not an unwritable, constant string constant).
If, on the other hand, you had written
char *namep = "yasser";
scanf("%s", namep);
you would have gotten the problems you expected. In this case, namep is a pointer, not an array. It's initialized to point to the string constant "yasser", which is not writable. When scanf tried to write to this memory, you probably would have gotten an error.
When you pass arrays to functions in C, they decay to pointers to the first item.
Therefore for:
char name[] ="yasser";
scanf("%s", name) is the same as scanf("%s", &name[0]) and either of those invocations should send shivers down your spine, because unless you control what's on your stdin (which you usually don't), you're reading a potentially very long string into a limited buffer, which is a segmentation fault waiting to happen (or worse, undefined behavior).
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp) {
char *myName = (char *) calloc(10, sizeof(char));
*(myName)='K'; *(myName+1)='h'; *(myName+2)='a'; *(myName+3)='l'; *(myName+4)='i'; *(myName+5)='d';
printf("%s\n",myName);
scanf("%s",myName);
printf("%s\n",myName);
return (EXIT_SUCCESS);
}
#include <stdio.h>
#include <string.h>
int main()//fonction principale
{
char name[10] ="yasser";
int longeur=0;
printf("%s\n",name);
scanf("%s",name);
longeur = strlen(name);
for (int i=0;i<longeur;i++) {
printf("%c",*(name+i));
}
return 0;}
I am appending a string using single character, but I am not able to get it right. I am not sure where I am making mistake. Thank you for your help in advance. The original application of the method is in getting dynamic input from user.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(){
int j;
char ipch=' ';
char intext[30]="What is the problem";
char ipstr[30]="";
printf("Input char: ");
j=0;
while(ipch!='\0'){
//ipch = getchar();
ipch = intext[j];
printf("%c", ipch);
strcat(ipstr,&ipch);
j++;
}
puts("\n");
puts(ipstr);
return;
}
Following is the output I am getting.
$ ./a.out
Input char: What is the problem
What is h e
p
oblem
change
strcat(ipstr,&ipch);
to
strncat(ipstr, &ipch, 1);
this will force appending only one byte from ipch. strcat() will continue appending some bytes, since there's no null termination character after the char you are appending. as others said, strcat might find somewhere in memory \0 and then terminate, but if not, it can result in segfault.
from manpage:
char *strncat(char *dest, const char *src, size_t n);
The strncat() function is similar to strcat(), except that
it will use at most n characters from src; and
src does not need to be null-terminated if it contains n or more characters.
strcat requires its second argument to be a pointer to a well-formed string. &ipch does not point to a well-formed string (the character sequence of one it points to lacks a terminal null character).
You could use char ipch[2]=" "; to declare ipch. In this case also use:
strcat(ipstr,ipch); to append the character to ipstr.
ipch[0] = intext[j]; to change the character to append.
What happens when you pass &ipch to strcat in your original program is that the function strcat assumes that the string continues, and reads the next bytes in memory. A segmentation fault can result, but it can also happen that strcat reads a few garbage characters and then accidentally finds a null character.
strcat() is to concatenate strings... so passing just a char pointer is not enough... you have to put that character followed by a '\0' char, and then pass the pointer of that thing. As in
/* you must have enough space in string to concatenate things */
char string[100] = "What is the problem";
char *s = "?"; /* a proper '\0' terminated string */
strcat(string, s);
printf("%s\n", string);
strcat function is used to concatenate two strings. Not a string and a character. Syntax-
char *strcat(char *dest, const char *src);
so you need to pass two strings to strcat function.
In your program
strcat(ipstr,&ipch);
it is not a valid statement. The second argument ipch is a char. you should not do that. It results in Segmentation Fault.
I want to calculate length of string and copy the string to another without using c library function, but when I use fgets() function to read the string from keyboard, the code not showing the actual value of length as well as the destination string. I use the fgets() function instead of gets() because the compiler says that gets()function is "deprecated".but when I change sizeof(source) in the code to an integer value suppose 50 the code works fine. Can anybody tell me what wrong with this code and why on earth the compiler say that gets() function is deprecated.
This is the code:
#include <stdio.h>
#include <stdlib.h>
int len(char *source);
char *coppy(char *dest,char *source);
int main (void){
char *source,*dest;
source=(char *)malloc(len(source)+1);
printf("enter string:");
fgets(source,sizeof(source),stdin);
if(source[len(source)-1]=='\n'){
source[len(source)-1]='\0';
}
dest=(char *)malloc(len(source)+1);
coppy(dest,source);
printf("dest=%s\n",dest);
printf("length source=%d\n",len(source));
printf("length dest=%d\n",len(dest));
return 0;
}
int len(char *source){
int i=0;
while(*source!='\0'){
source++;
i++;
}
return i;
}
char *coppy(char *dest,char *source){
while(*source!='\0'){
*dest=*source;
source++;
dest++;
}
*dest='\0';
return dest;
}
This is the result when run that code:
enter string:programming
dest=pro
length source=3
length dest=3
Here is your first mistake:
source=(char *)malloc(len(source)+1)
You pass source to the function len before you initialized it, which is undefined behaviour. From hereon in, anything could happen.
The second mistake is your use of fgets:
fgets(source,sizeof(source),stdin);
The second argument to fgets is supposed to be how many characters are available to be written in, not sizeof(source). Read the documentation for fgets, and sizeof if necessary.
Your error is in how you allocate memory for source
source=(char *)malloc(len(source)+1);
What did you expect len(source) to be? Play computer and run through your len function. I'm surprised your code compiles and runs at all. Your len function on an uninitialized char* should be undefined behavior.
That is why your code fails, you are not allocating enough memory to hold your input string.