So I have a homework assignment to do for Friday and I am having some trouble figuring out why this is happening. Here is the code:
while(curVal < length)
{
code[word][wordVal] = input[curVal];
if(input[curVal + 1] == 32) //Is the current char in the input a space
{
word++;
curVal++;
wordVal = -1;
}
curVal++;
wordVal++;
}
After this I print it out in a ncurses window. For the input "Lucas is great" the output is:
Lucas^D
is
great
The problem I am having is instead of printing "Lucas" it prints "Lucas^D". If anyone understand what my code is doing and can hep me fix it I would really appreciate it.
A string in C consists of an array of characters with a NUL character at the end. The NUL character can be written as '\0'. If you forget to put the NUL character at the end of your string, then all sorts of bad things can happen, including printing garbage characters and/or crashing your program.
So you have two choices. You can fill the whole array with NUL characters before you start
memset( code, '\0', sizeof(code) );
Or you can insert the NUL character when you find the end of the string.
if(input[curVal + 1] == ' ') //Is the current char in the input a space
{
code[word][wordval] = '\0';
word++;
Code does not terminate the char array properly with a '\0' to make the array a string. Thus causes subsequent printing to be amiss - likely undefined behavior.
The terminating null character '\0' should be added after each code[word][wordVal] assignment.
code[word][wordVal] = input[curVal];
// add
code[word][wordVal + 1] = '\0';
To add it inside the if(input[curVal + 1] == 32) block risks it not being set should curVal < length become false before a space is encountered.
When you copy words from input to code, you need to zero-terminate them (C strings are terminated by an extra zero byte):
code[word][wordVal] = input[curVal];
if (32 == input[curVal]) {
// The character we just read was a space.
// Transform it into a terminator.
code[word][wordVal] = 0x0;
wordVal = 0; // Prepare to write at first character...
word++; // ...of next word.
} else {
wordVal++; // Next character
}
curVal++; // Next input byte
Then you also have to terminate the last word when you reach the end of the input.
Related
I don't quite understand this program. I don't understand what is happening in the for loop. Can someone explain to me in simple words. And the site also didn't explain it well-enough. This is the link to the site. https://www.geeksforgeeks.org/print-words-string-reverse-order/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void printReverse(char str[])
{
int length = strlen(str);
FILE *fptr;
if((fptr=fopen("Question1.txt","w"))==NULL)
{
printf("Invalid file");
exit(0);
}
int i;
for (i = length - 1; i >= 0; i--) {
if (str[i] == ' ')
{
str[i] = '\0';
printf("%s ", &(str[i]) + 1);
fprintf(fptr,"%s ", &(str[i]) + 1);
}
}
fprintf(fptr,"%s",str);
printf("%s.", str);
fclose(fptr);
}
int main()
{
char str[1000];
//clrscr();
printf("Enter string: ");
scanf("%[^\n]s", str);
printReverse(str);
//getch();
return 0;
}
In the for loop, why put &(str[i])+1? And also in printf("%s.", str)--this only has the first word; how?
Okay, let's see if I can help. I'll go through the code carefully.
I suspect you already understand this. It's just a method call.
void printReverse(char str[])
{
strlen is a standard method that returns the length of a null-terminated string. That means that str might contain Hello (5 characters), but there's one more byte with a 0 in it, which is how C has always marked the end of the string. In this case, str itself takes 6 bytes, but length will be 5.
int length = strlen(str);
This is how you open a file in C. C++ has better ways. The file is written for writing.
FILE *fptr;
if((fptr=fopen("Question1.txt","w"))==NULL)
{
printf("Invalid file");
exit(0);
}
Here's your for-loop. Let's assume str contains Hello, so length is 5, but the indexes into string are str[0..4]. C uses the index as "offset from the beginning", so the first element is 0, not 1. Thus, when this loop starts, str[i] == o (using Hello as our example string). We then loop, decrementing i each time. Once i goes below 0, the loop ends.
int i;
for (i = length - 1; i >= 0; i--) {
Okay, remember we're printing the words in normal order, but the words themselves are in reverse order. So this looks for a space -- between words. So if we use Hello there as our input text, this if-statement is true when i is pointing to the space between the two words.
Now here's the trick. Remember what I said earlier about null-terminated strings? What this does is to step on that space and replace it with a 0. That makes the rest of this magic work.
if (str[i] == ' ')
{
str[i] = '\0';
And here's the magic. Now, this is a strange way to do it. I would have done it with &str[i+1], but this works. What this is doing is saying "Print the string that begins after the space we just clobbered." We do it to the terminal and the file.
printf("%s ", &(str[i]) + 1);
fprintf(fptr,"%s ", &(str[i]) + 1);
}
}
This writes the produced rearranged string to the file that was opened as well as to your terminal then makes sure the file is closed.
fprintf(fptr,"%s",str);
printf("%s.", str);
fclose(fptr);
}
This all works because we step on the spaces with a zero. For Hello world, we:
Start from the tail
Find the space and stick a zero in it
Print world
Keep backing up to the end of the data.
Drop out of the for-loop and print whatever is left: Hello
Answer to your specific questions
In the for loop why put? &(str[i])+1?
&str[i] is the address of the character at index i where a space has been replaced with a NUL character. With +1 you get the address of the character after it, i.e. the beginning of the word that follows the space that was just replaced. (In case of double spaces this would result in an empty string.)
And also in printf("%s.", str); this only has the first word how?
Assuming the first word is not preceded by a space, the loop will not print it.
This printf("%s.", str); will print the string from the beginning until the first NUL character that replaces a former space character, hence resulting in the first word.
Additional question from comment
So... for example if I input Hello World does the W in that get the index 0?
The W is at index 6. (H is 0, e is 1 etc.)
When i has been counted down to 5, the space at this position will be replaced with a NUL ('\0') character, and it will print the remaining string from the W up to the end of the string which is also marked by a NUL character. (As defined by the C standard.)
And what if the character is not a NULL character? Then it won't go execute if right? It'll just increment i again till it encounters another NULL right?
I don't fully understand these questions. In case there was no NUL character at the end of the string printf would read past the end of the string leading to undefined behavior.
In case of an input string Hello World and Universe", all spaces after Worldwould have been replaced with NUL characters before, so when the program reaches the position of the space beforeWorld`, the string will be
Hello World\0and\0Universe\0
before the replacement and
Hello\0World\0and\0Universe\0
after the replacement.
I have two char arrays (char string1[7] and char string2[256]) which I need to print in a specific format. Both strings have a random number of entries terminated with a '\0' null byte.
I need to print string1
followed by a space on 9th character
followed by string2 - which MUST begin printing from the 10th character onwards.
I have tried implementing this by copying the strings to a new array which I can print directly, however it is not working.
while(string2[i]!='\0')
{
if(i<9 && string1[i]!='\0')
{
Printline[i]=string1[i];
}
else if (i>9)
{
Printline[i]=string2[i];
}
i++;
}
printf("%s\n",Printline);
Any help is much appreciated :)
int main(void) {
char string1[7];
char string2[256];
strncpy(string1, "str1", 6);
strcpy(string2, "This is string 2.");
printf("%-8s %s", string1, string2);
return 0;
}
When compiled and run, the code above will print out:
str1 This is string 2.
The %-8s format specification says that, if the given string of characters is less than 8 characters long (not including '\0'), the string will be followed by whitespaces (blanks) to take up 8 rooms.
Furthermore, the 9th character is going to be a space and the rest will be filled up by string2.
Edit: strncpy function is used for string1 to ensure that no more than 6 characters will be copied from src to dest. Keep in mind that the 7th character will be a null-terminator ('\0').
I believe the following needs to be corrected/clarified and not going to post the code, so that you would have a chance to learn and try to fix it.
while(string2[i]!='\0') /* and further checks in the code, it appears that
the string2 has larger set of characters and
exceeds a count of 9 */
{
if (i<9 && string1[i]!='\0') /* What happens when (i < 9)
but string1[i] has already
reached the '\0'? */
{
Printline[i]=string1[i];
}
else if (i>9)
{
Printline[i]=string2[i];
}
/* What about (i == 9)? */
i++;
}
/* Not including '\0' from string2 before printing Printline
would eventually crash the program */
printf("%s\n",Printline);
I have an array of charracters where I put in information using a gets().
char inname[30];
gets(inname);
How can I add another character to this array without knowing the length of the string in c? (the part that are actual letters and not like empty memmory spaces of romething)
note: my buffer is long enough for what I want to ask the user (a filename, Probebly not many people have names longer that 29 characters)
Note that gets is prone to buffer overflow and should be avoided.
Reading a line of input:
char inname[30];
sscanf("%.*s", sizeof(inname), inname);
int len = strlen(inname);
// Remove trailing newline
if (len > 0 && inname[len-1] == '\n') {
len--;
inname[len] = '\0'
}
Appending to the string:
char *string_to_append = ".";
if (len + strlen(string_to_append) + 1) <= sizeof(inname)) {
// There is enough room to append the string
strcat(inname, string_to_append);
}
Optional way to append a single character to the string:
if (len < sizeof(inname) - 2) {
// There is room to add another character
inname[len++] = '.'; // Add a '.' character to the string.
inname[len] = '\0'; // Don't forget to nul-terminate
}
As you have asked in comment, to determine the string length you can directly use
strlen(inname);
OR
you can loop through string in a for loop until \0 is found.
Now after getting the length of prvious string you can append new string as
strcat(&inname[prevLength],"NEW STRING");
EDIT:
To find the Null Char you can write a for loop like this
for(int i =0;inname[i] != 0;i++)
{
//do nothing
}
Now you can use i direcly to copy any character at the end of string like:
inname[i] = Youe Char;
After this increment i and again copy Null char to(0) it.
P.S.
Any String in C end with a Null character termination. ASCII null char '\0' is equivalent to 0 in decimal.
You know that the final character of a C string is '\0', e.g. the array:
char foo[10]={"Hello"};
is equivalent to this array:
['H'] ['e'] ['l'] ['l'] ['0'] ['\0']
Thus you can iterate on the array until you find the '\0' character, and then you can substitute it with the character you want.
Alternatively you can use the function strcat of string.h library
Short answer is you can't.
In c you must know the length of the string to append char's to it, in other languages the same applies but it happens magically, and without a doubt, internally the same must be done.
c strings are defined as sequences of bytes terminated by a special byte, the nul character which has ascii code 0 and is represented by the character '\0' in c.
You must find this value to append characters before it, and then move it after the appended character, to illustrate this suppose you have
char hello[10] = "Hello";
then you want to append a '!' after the 'o' so you can just do this
size_t length;
length = strlen(hello);
/* move the '\0' one position after it's current position */
hello[length + 1] = hello[length];
hello[length] = '!';
now the string is "Hello!".
Of course, you should take car of hello being large enough to hold one extra character, that is also not automatic in c, which is one of the things I love about working with it because it gives you maximum flexibility.
You can of course use some available functions to achieve this without worrying about moving the '\0' for example, with
strcat(hello, "!");
you will achieve the same.
Both strlen() and strcat() are defined in string.h header.
I am learning C now and I'm at the point where I don't really get what is the difference of initializing the end of the string with NULL '\0' character. Below is the example from the book:
#include <stdio.h>
#include <string.h>
int main(){
int i;
char str1[] = "String to copy";
char str2[20];
for(i = 0; str1[i]; i++)
str2[i] = str1[i];
str2[i] = '\0'; //<====WHY ADDING THIS LINE??
printf("String str2 %s\n\n", str2);
return 0;
}
So, why do I have to add NULL character? Because it works without that line as well. Also, is there a difference if I use:
for (i = 0; str1[i]; i++){
str2[i] = str1[i];
}
Thanks for your time.
The line you're referring to is added in general use for safety. When you copy values to a string you always want to be sure that it's null terminated, otherwise when reading the string it will continue past the point where you want the end of that string to be (because it doesn't know where to stop due to lack of the null terminator).
There is no difference with the alternate code you posted since you are separating only the line below the for statement to be in the loop, which happens by default anyway if you don't use the curly braces {}
In C, the end of the string is detected by the null character. Consider the string 'abcd'. If the variable in the actual binary have the next variable immediately after the 'd' character, C will think that the next characters in the platform are part of that string and you will continue. This is called buffer overrun.
Your initial statement allowing 20 bytes for str2 will usually fill it with 20 zeroes, However, this is not required and may not occur. Additionally, let us say you move a 15 character string into str2. Since it starts with 20 zeroes, this will work. However, say that you then copy a 10 character string into str2. The remaining 5 characters will be unchanged and you will then have a 15 character string consisting of the new 10 characters, followed by the five characters previously copied in.
In the code above the for loop says move the character in str1 to str2 and point to the next character. If the character now pointed to in str1 is not 0, loop back and do again. Otherwise drop out of the loop. Now add the null character to the end of the str2. If you left that out, the null character at the end of str1 would not be copied to str2, and you would have no null character at the end of str2.
This can be expressed as
i = 0;
label:
if (str1[i] == 0) goto end;
str2[i] = str1[i];
i = i + 1;
goto label;
end: /* This is the end of the loop*/
Note that the '\0' character has not yet been moved into str2.
Since C requires brackets to show the range of the for, only the first line after the for is part of the loop. If i had local scope and is lost after the loop, you would not be able to just wait to fall out of the loop and make it 0. You would no longer have a valid i pointer to tell you where in str2 you need to add the 0.
An example is C++ or some compilers in C which would allow (syntactically)
for (int i = 0; str1[i]; i++)
{
str2[i] = str1[i];
}
str2[i] = 0;
This would fail because i would be reset to whatever it happened to be before it entered the loop (probably 0) as it falls out of the loop. If it had not been defined before the loop, you would get an undefined variable compiler error.
I see that you fixed the indentation, but had the original indentation stayed there, the following comment would apply.
C does not work solely by indentation (as Python does, for example). If it did, the logic would be as follows and it would fail because str2 would be overwritten as all 0.
for (int i = 0; str1[i]; i++)
{
str2[i] = str1[i];
str2[i] = 0;
}
You should only add a \0 (also called the null byte) in the end of the string. Do as follows:
...
for(i = 0; str1[i]; i++) {
str2[i] = str1[i];
}
str2[i] = '\0'; //<====WHY ADDING THIS LINE??
...
(note that I simply added braces to make the code more readable, it was confusing before)
For me, that is clearer. What you were doing before is basically take advantage of the fact that the integer i that you declared is still available after you ran the loop to add a \0 in the end of str2.
The way strings work in C is that they are basically a pointer to the location of the first character and string functions (such as the ones you can find in string.h) will read every single char until they find a \0 (null byte). It is simply a convention for marking the end of the string.
Some further reading: http://www.cs.nyu.edu/courses/spring05/V22.0201-001/c_tutorial/classes/String.html
'\0' is used for denoting end of string. It is not for the compiler, it is for the libraries and possibly your code. C does not support arrays properly. You can have local arrays, but there is no way to pass them about. If you try you just pass the start address (address of first element). So you can ever have the last element be special e.g. '\0' or always pass the size, being careful not to mess up.
For example:
If your string is like this:
char str[]="Hello \0 World";
will you tell me what would display if you print str ?
Output is:
Hello
This will be the case in character arrays, Hence to be in safer side, it is good to add '\0'at the end of string.
If you didnt add '\0', some garbage values might get printed out, and it will keep on printing till it reached '\0'
In C, char[] do not know the length of the string. It is therefore important character '\0' (ASCII 0) to indicate the end of the string. Your "For" command will not copy '\0', so output is a string > str2 (until found '\ 0' last stop)
Try:
#include <stdio.h>
#include <string.h>
int main(){
int i;
char str[5] = "1234";
str[4] = '5';
printf("String %s\n\n", str);
return 0;
}
I have a snippet of C code:
I want to add a new line character at certain intervals. The problem is, when I add it in the if block, on the next iteration, strcat takes it away, then concats s on, and then puts the \n at the end.
I can think of any other way to do this so strcat does not remove the \n that I want to add.
Any ideas?
hmm... if curPos points to the the next available position in the array, than I would do this. curPos + 1 points after the current '\0' termination of ans, since arrays in C are indexed starting at 0.
if (i % 8 == 0 && i != 0)
{
ans[curPos++] = '\n';
ans[curPos] = '\0'; /* always null terminate a string after any extension */
}