Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I tried inputting the null character into the list of delimiters but it would not accept it. I tried inputting "\0" but it wouldn't accept it. I even tried putting in the double quotes with escape characters but it still would not accept it.
Is there a way I could do this?
According to strtok(3) this function is used to isolate sequential tokens in a null-terminated string. So the answer is no, not using strtok, since that function cannot compare a \0 separator from the terminator. You will have to write your own function (which is trivial).
Also read the BUGS section in the strtok man page ... better avoid using it.
If you are allowed to end your string with a double \0 as sentinel you can build your own function, something like:
#include <stdio.h>
#include <string.h>
int main(void)
{
char *s = "abc\0def\0ghi\0";
char *p = s;
while (*p) {
puts(p);
p = strchr(p, '\0');
p++;
}
return 0;
}
Output:
abc
def
ghi
For better or worse, C decided that all strings are null terminated, so you can't parse based on that character.
One workaround would be to replace all nulls in your (non-string) binary buffer with something you know doesn't occur in the buffer, then use that as your separator treating the buffer as char*.
In C, strings are just char arrays that must end with a null character. If a string in memory is not terminated that way, the program will endlessly read memory until a null char is found and there is no way to determine where it will be since memory changes constantly. Your best bet is to create an array of char pointers (strings) and populate them using better organization.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I need to write a program where the program needs to loop and get input from the user. In order to break the loop, the user will need to type exit on the keyboard.
The following is my code:
int main()
{
char input[100];
char terminate[100]="$exit";
//if input does not equals to terminate keep asking user for input
while(strcmp(input, terminate)!=0)
{
printf("$");
fgets(input,100,stdin);
}//otherwise, exit the program
}
I tried testing the code above but it keeps on looping even after typing the word exit. Your assistance is greatly appreciated. :)
fgets will read the EOL character which will be included in the final string.
You may use strncmp to just use the characters from "terminate": strncmp(input, terminate, strlen(terminate).
There are two (and possibly three) problems in your code as you show it:
The first, which is very serious, is that you use input before it's initialized. That means the contents of the array is indeterminate (and could be seen as "random" or "garbage"). That will very likely lead to undefined behavior when you use it in strcmp because it's not a proper null-terminated string.
The second problem is that fgets adds the ending newline in the buffer, so unless you remove it or add a newline in the string you compare with the strings will never be equal.
You can easily remove the newline from the input string by using the strcspn function:
input[strcspn(input, "\n")] = 0;
The possible third problem is that you seem to be adding the prompt $ in the string you compare. Unless the user actually writes the $ in the input given, it will not be part of the input.
You also don't need to use as many characters for the terminate array. Instead let the compiler decide the proper amount:
char terminate[] = "exit"; // The size of the array will be 5, including null-terminator
Figured it out. Here is my solution:
while(strncmp(input, terminate,4)!=0)
{
printf("$");
fgets(input,100,stdin);
}
use strncmp instead of strcmp.
This question already has answers here:
What happened when we do not include '\0' at the end of string in C?
(5 answers)
Closed 4 years ago.
so I know that in C, that '\0' is the null character, used to terminate strings. I've been looking online to see what it actually does, and I've run programs with and without it in my strings to see the difference in its use and non-use. I can't find any.
What can I not do when my strings lack the '\0' character?
Code that worked for me without a \0:
char a[10] = {'a','b','c','d','e','f','g'};
int x = strlen(a);
char b[10] = {'h','i','j','k','l'};
int y = strcmp(a,b);
printf("%d\n",x);
printf("%d\n",y);
According to the standard (C11 ยง7.1.1), if it doesn't end with a null byte it is not technically a 'string', it is simply a char array. (Make no mistake c-strings are char arrays as well, but they end in a terminator.)
You won't be able to use many of the string functions strcat, strcmp, strcpy, strlen, printf, etc, without a lot of your own built-in safeguards. Note, you can perform similar operations if you keep track of the length of the string manually and use functions like memcpy, strnlen, sprintf, etc, but you aren't technically working with c-string when doing so, you're simply working with arrays.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have the following code:
char* realtor_command[120];
for(int i=0;i<REALTOR_MAX_COMMAND_LENGTH;i++){
realtor_command[i]=malloc(sizeof(120));
}
realtor_command[0]="test_string"
realtor_command[1]="next_test_string"
When I use strlen(realtor_command[0]) I get wrong value, I read in previous questions this happens because its an array and not pointer, yet I haven't found any fix for this problem.
My question is if there is anyway to get the length of realtor_command[i]?
Thank you very much.
EDIT :
This is how I invoke strlen :
char* matrix=malloc(strlen(realtor_command[8])+1);
In this code:
char* realtor_command[120];
for(int i=0;i<REALTOR_MAX_COMMAND_LENGTH;i++){
realtor_command[i]=malloc(sizeof(120));
}
You create an array of 120 strings, then loop through REALTOR_MAX_COMMAND strings (presumably this should be 120?) and set them to newly allocated 4- or 8-byte strings (sizeof(120) means sizeof(int) which is either 4 or 8 bytes). Since those strings are newly allocated, they will contain arbitrary data, and may not end with a null-terminator.
This is important because strlen() just loops over the string until it finds a null terminator, so it can't work with non-null-terminated strings.
You could add a null terminator yourself, but then the strings would contain arbitrary garbage up to the end of the string, and they may have null terminators inside them. You could make them start with a null-terminator, but then strlen() would always return 0.
What might be better is to allocate these strings when you actually fill them, and leave them as null pointers until then:
char* realtor_command[120];
for (int i = 0; i < 120; i++) {
realtor_command[i] = NULL;
}
char input_buffer[REALTOR_MAX_COMMAND];
// Read in one string, then copy it so we can re-use the buffer
fgets(input_buffer, REALTOR_MAX_COMMAND, stdin);
realtor_command[0] = strdup(input_buffer);
This will also avoid the memory leak in your code.
Note that you'll probably want to make sure the string read by fgets contains a newline, to make sure the input fit in your buffer:
if (strstr(input_buffer, "\n") == NULL) {
// error, input didn't fit in our buffer!
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
(I am very bad at inputting/processing strings in C. Hope this question will teach me a lot.)
I am trying to make a function that will input an arithmatic string from stdin, e.g 23 + 45 * 6 - 5, and return the value.
There are multiple strings, entered one after another, and can be of any length and the operator precedence doesn't matter, i.e., it processes string sequentially.
The problems that I faced are :-
\n from previous string is also considered a string.So if I input 3 strings , it will actually be 6, 3 strings and 3 \n.
I used a char pointer and used char * input; scanf(" %s",input);, but in addition to above problem, I also get segmentation fault, which I guess is due to missing \0.
My question is forget what mess I did, what would you have done or what's the best way to handle string input in the above scenario. A dummy code is sufficient.Thanks.
What I was doing
#include <stdio.h>
int main()
{
int t; //no of test cases
char input;
scanf("%d",&t);
while(t--)
{
while((input=getchar())!='\n')
{
//use switch to identify char and follow appropriate action
printf("%c\n",input );
}
}
return 0;
}
As suggested by Joachim Pileborg, use fgets. Use a char array, instead of one char variable, to store the string.
char input[100];
fgets(input, sizeof(input), stdin);
The advantage of fgets over sscanf is that fgets can read spaces in your input.
It will include the end-of-line byte \n, so 3 strings will not turn into 6 strings.
As usual with fgets, there is an arbitrary limit on the length of the input. If the user inputs something longer than 98 bytes, the system cannot fit it all (plus end-of-line \n and end-of-string \0 bytes), and the program will receive truncated string.
If you cannot tolerate that, use getline (it's harder to use, so use fgets if in doubt).
After you scan your string in, check to see if it is a '\n', if it is just ignore processing it and move to the next one.
Or you could try:
char input[101];
scanf("%s\n", &input);
First of all. Your idea of writing an fomular expression analyzer as a first projekt is not a very good one. Start with a simpler project.
You get the sagmentation fault, because you try to read data (with the scanf()) into a not initialized pointer.
char *input;
will not allocate any memory for the string you want to read with scanf(). You have to use a buffer something like
char input[256];
and give the pointer to the buffer to scanf("%s",input) (oder for better understanding scanf("%s",&input[0]);
Anywhere, this buffer has only 255 chars to store and you must be aware, that if you enter more then 255 chars in the scanf() you will get an illegal memory access as well.
Claus
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
#include
int main(void)
{
char str[100]="88888888888888";
char t[20]="";
gets(t);
puts(str);
puts(t);
return 0;
}
The first line
555555555555555555555555555555555
is put in.
Why str is 55555555555? Why str isn't 88888888888888888 or 55555555555588888?
You overriden the t buffer, and reached the str buffer, where the rest of the input, and the null terminator was set. And puts prints only until the null terminator.
Pretty much looks like that:
[ t (20) ][str(100) ]
55555555555555555555 5555555555555\0
Note that although t is declared as char[20], when you print it you get the full input (longer than 20), since puts stops at the null terminator (again).
BTW, this is a buffer overflow, not a stackoverflow, but stack overflow is possible on this codeas well.
As Binyamin said it is caused by the overflow you trigger because of the input string being too long. However it is a bit random thing - sometimes the two memory allocations will happen just next to each other and the string will extend to the neighbouring variables, sometimes it might not happen.
I advise you to place guard conditions for such kind of overflows.
If you see in the gets documentation:
Notice that gets does not behave exactly as fgets does with stdin as
argument: First, the ending newline character is not included with
gets while with fgets it is. And second, gets does not let you specify
a limit on how many characters are to be read, so you must be careful
with the size of the array pointed by str to avoid buffer overflows.
In your case if you do not know the size apriory maybe it is better idea to use fgets as it is more secure (though a bit slower).
When you enter a string of more than 20 5s, it overruns the buffer that was allocated to t and extends into the buffer that was allocated to str.
Then it displays the contents of str, which is the string you entered, starting at the 21st character.
Finally, it displays the contents of t, but since that string doesn't end with a null character, it continues displaying memory (which is the buffer assiged to str) until it encounters the null character after all the 5s.
In order to avoid those allocation overlapping issues you can try this alternative, so that the allocation takes place at runtime if I'm not wrong:
#include <iostream>
int main(void)
{
char *str;
char *t;
str = new char(100);
str = (char*)"88888888888888";
t = new char(20);
std::cin >> t;
puts(str);
puts(t);
return 0;
}