I am a very new programmer and I have been having a hard time figuring this out. I have looked online but I can't seem to find a clear answer. How do I go about replacing a desired substring by another in C?
I basically would like the user to be able to edit their string if they wanted to.
I know how to get the following:
The index from where to start making the edit
The length of the new substring to be added
I was wondering how do I then go about inserting the new substring and deleting the old one?
Any Help would be so appreciated
This is my code:
int length;
char firstString[100];
char editIndex[100];
char newString[100];
Char editedString[100];
printf("Enter your string: \n");
fgets(firstString, 100, stdin);
printf("Enter the word from which you would like to start editing: \n");
fgets(editIndex, 100, stdin);
printf("What substring would you like there instead?\n");
fgets(newString, 100, stdin);
length = strlen (newString);
This is where I get confused, I have the index from where to start the index (the first character of the word, and I know how long the edit is. I just don't know how to delete the original character(s) that were there and replace it by the new ones. I thought of using a for loop but I am not sure it would work.
This is what I would like to have as an end result:
printf("%s", editedString);
and then this printing the edit the user has made.
You will need a loop that iterates from the index of where to start making the edit and ends when the index is the length of the substring from the starting point setting the characters all the way. It needs to be careful not to overrun past the length of the original string.
Example
char theString[10] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};
char theSubString[5] = {'E', 'a', 'r', 't', 'h'};
for (int i = 0; i < 5, i++)
theString[5 + i] = theSubString[i];
This replaces the desired substring "World" with the string "Earth"
"HelloWorld"
becomes
"HelloEarth"
The problem you're facing here is how strings are stored in C. Strings in C are simply stored as an array of chars, with a terminating NULL character (\0). That information leads to the answer to your question, as well as a problem with what you're trying to do.
The problem is that because strings are saved as arrays, the string that you are trying to insert must be the same length as the string you are removing. Otherwise, if the new string is shorter than the old, you'll end up not fully removing the old string, and if the new string is longer than the old, you'll be overwriting other characters not included in the old string. To implement this so that the strings can be of different lengths, your code is going to have to account for the change in number of letters and shift other letters around in the word accordingly. Don't forget that if you shift letters further down the string, you also have to move the NULL character at the end and that you're not going beyond the end of the array.
The solution, though, is that because it's only an array of characters, individual characters can be accessed (and changed) simply by using array subscripts. If you can find the index of your substring, you can simply copy in your new string letter by letter.
int delete_substring (char *str, char *substr) {
char *loc = strstr (str, substr); // find position of substring
if (!loc) return -1; // not found
int sublen = strlen (substr);
for (int i = loc - str;; i++) {
str [i] = str [i + sublen]; // move characters left overwriting substr positions
if (str [i] == '\0') break; // moved the end of string char, we are done
}
return loc - str; // use pointer difference to return the integer where substr found
}
Related
I don't understand Why don’t we have to print strings in for loop ? In normal cases we need to print arrays in for loop. For example, if we want to print the array of integers. It will be like this:
int a[n];
for (i = 0; i < n; i++){
printf("%d", a[i]);
}
But for strings like:
char s[100] = " Hello ";
printf("%s\n", s);
it is enough to write the name of array.
EDIT: It seems like I didnt ask my question properly as some of you wrote answers which is not related to my question.I edit my question.
Strings terminate with the empty character '\0', that's how it is possible to know when a string ends even without explicitly passing its length.
The difference is that C-style strings (which are char arrays) are zero-terminated, whereas int arrays are normally not zero terminated.
Theoretically, you could also create an int array which is zero-terminated and print that in a loop:
int a[] = {5,7,3,0};
for (i=0;a[i]!=0;i++)
{
printf("%d",a[i])
}
However, the problem with zero-terminated int arrays is that the number 0 could be a meaningful value, so you cannot be sure that it really is the end of the array when you encounter that value. With strings, however, the ASCII-Code 0 does not represent a meaningful value, so you can be reasonably sure that you have reached the end of the string.
Your example is far from analogous. %d refers to a single integer, while %s refers to an entire (but still single) string.
You are not passing the size of the array n[] to printf either - rather you are calling printf n times. You are printing one int just as you are printing one string.
The actual string length is not known a priori, rather printf iterates the string until it encounters the \0 terminator. Equivalent to:
for( int i = 0; s[i] != '\0'; i++)
{
printf( "%c", s[i] ) ;
}
because
char s[100] = " Hello ";
is equivalent to:
char s[100] = { ' ', 'H', 'e', 'l', 'l', 'o', ' ', '\0' } ;
Strings are multiple characters all at once. You cannot ask for a specific character from a string. If you want to do so, you must refer to it as an array of chars like this
for (i = 0; i < n; i++){
printf("%c", s[i]);
}
It is because you are already providing the parameter which is "%s" to the printf function which already has a definition telling it how to print a string.
Hope it helps.
One of the reason is that char only takes 1 byte of memeory and when you just press a character, the first index of array is filled up completely and it moves on to the next one till it encounters NULL character. This is not the case with integer array where the size is more than 1 byte and is machine dependent. So you cannot escape the first index by just pressing the number less than the maximum range. If you try to do this, it will store your numbers in first index only and hence a for loop is required there.
So I just read an example of how to create an array of characters which represent a string.
The null-character \0 is put at the end of the array to mark the end of the array. Is this necessary?
If I created a char array:
char line[100];
and put the word:
"hello\n"
in it, the chars would be placed at the first six indexes line[0] - line[6], so the rest of the array would be filled with null characters anyway?
This books says, that it is a convention that, for example the string constant "hello\n" is put in a character array and terminated with \0.
Maybe I don't understand this topic to its full extent and would be glad for enlightenment.
The \0 character does not mark the "end of the array". The \0 character marks the end of the string stored in a char array, if (and only if) that char array is intended to store a string.
A char array is just a char array. It stores independent integer values (char is just a small integer type). A char array does not have to end in \0. \0 has no special meaning in a char array. It is just a zero value.
But sometimes char arrays are used to store strings. A string is a sequence of characters terminated by \0. So, if you want to use your char array as a string you have to terminate your string with a \0.
So, the answer to the question about \0 being "necessary" depends on what you are storing in your char array. If you are storing a string, then you will have to terminate it with a \0. If you are storing something that is not a string, then \0 has no special meaning at all.
'\0' is not required if you are using it as character array. But if you use character array as string, you need to put '\0'. There is no separate string type in C.
There are multiple ways to declare character array.
Ex:
char str1[] = "my string";
char str2[64] = "my string";
char str3[] = {'m', 'y', ' ', 's', 't', 'r', 'i', 'n', 'g', '\0'};
char str4[64] = {'m', 'y', ' ', 's', 't', 'r', 'i', 'n', 'g' };
All these arrays have the same string "my string". In str1, str2, and str4, the '\0' character is added automatically, but in str3, you need to explicitly add the '\0' character.
(When the size of an array is explicitly declared, and there are fewer items in the initializer list than the size of the array, the rest of the array is initialized with however many zeros it takes to fill it -- see C char array initialization and The N_ELEMENTS macro .).
When/Why is '\0' necessary to mark end of an (char) array?
The terminating zero is necessary if a character array contains a string. This allows to find the point where a string ends.
As for your example that as I think looks the following way
char line[100] = "hello\n";
then for starters the string literal has 7 characters. It is a string and includes the terminating zero. This string literal has type char[7]. You can imagine it like
char no_name[] = { 'h', 'e', 'l', 'l', 'o', '\n', '\0' };
When a string literal is used to initialize a character array then all its characters are used as initializers. So relative to the example the seven characters of the string literal are used to initialize first 7 elements of the array. All other elements of the array that were not initialized by the characters of the string literal will be initialized implicitly by zeroes.
If you want to determine how long is the string stored in a character array you can use the standard C function strlen declared in the header <string.h>. It returns the number of characters in an array before the terminating zero.
Consider the following example
#include <stdio.h>
#include <string.h>
int main(void)
{
char line[100] = "hello\n";
printf( "The size of the array is %zu"
"\nand the length of the stored string \n%s is %zu\n",
sizeof( line ), line, strlen( line ) );
return 0;
}
Its output is
The size of the array is 100
and the length of the stored string
hello
is 6
In C you may use a string literal to initialize a character array excluding the terminating zero of the string literal. For example
char line[6] = "hello\n";
In this case you may not say that the array contains a string because the sequence of symbols stored in the array does not have the terminating zero.
You need the null character to mark the end of the string. C does not store any internal information about the length of the character array or the length of a string, and so the null character/byte \0 marks where it ends.
This is only required for strings, however – you can have any ordinary array of characters that does not represent a string.
For example, try this piece of code:
#include <stdio.h>
int main(void) {
char string[1];
string[0] = 'a';
printf("%s", string);
}
Note that the character array is completely filled with data. Thus, there is no null byte to mark the end. Now, printf will keep printing until it hits a null byte – this will be somewhere past the end of the array, so you will print out a lot of junk in addition to just "a".
Now, try this:
#include <stdio.h>
int main(void) {
char string[2];
string[0] = 'a';
string[1] = '\0';
printf("%s", string);
}
It will only print "a", because the end of the string is explicitly marked.
The length of a C string (an array containing the characters and terminated with a '\0' character) is found by searching for the (first) NUL byte. \0 is zero character. In C it is mostly used to indicate the termination of a character string.
I make an example to you:
let's say you've written a word into a file:
word = malloc(sizeof(cahr) * 6);
word = "Hello";
fwrite(word, sizeof(char), 6, fp);
where in word we allocate space for the 5 character of "Hello" plus one more for its terminating '\0'. The fp is the file.
An now, we write another word after the last one:
word2 = malloc(sizeof(cahr) * 7);
word2 = "world!";
fwrite(word2, sizeof(char), 7, fp);
So now, let's read the two words:
char buff = malloc(sizeof(char)*1000); // See that we can store as much space as we want, it won't change the final result
/* 13 = (5 chacater from 'Hello')+(1 character of the \0)+(6 characters from 'world!')+(1 character from the \0) */
fread(buff, sizeof(char), 13, fp); // We read the words 'Hello\0' and 'world!\0'
printf("the content of buff is: %s", buff); // This would print 'Hello world!'
This last is due to the ending \0 character, so C knows there are two separated strings into buffer. If we had not put that \0 character at the end of both words, and repeat the same example, the output would be "Helloworld!"
This can be used for many string methods and functions!.
In K&R, we are introduced to char arrays to represent strings.
Arrays are passed by reference. From what I understand, we can point to the first element in an array (pointer?). Using the char array input without really defining its values means it sets garbage data inside the array. (Honestly not really sure what garbage data is, maybe nulls?).
Anyways, initially the empty char array is passed to function getLength, and it sets char array inputs. In my code, I display the len and char array input.
On the next input, I call getLength again, and pass the same char array input. I set the values like before and return the length.
How is the old input erased? Aren't I referencing the exact same array that previously stored the previous input? Below my code, I'll show an example.
#include <stdio.h>
#define MAXLINE 1000 /* For allocating storage size for char array */
int getLength(char s[]); /* set char array and return length */
int main(void) {
int len;
char input[MAXLINE];
while ((len = getLength(input)) > 0) {
printf("len = %d\n", len);
printf("string = %s", input);
}
}
int getLength(char s[]) {
int i, c;
for (i = 0; i < MAXLINE - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {
s[i] = c;
}
if (c == '\n') {
s[i++] = '\n';
}
s[i] = '\0';
return i; /* return length including newline */
}
Example:
Input: "Hello my name is Philip"
Output: "len = 24"
"string = Hello my name is Philip"
Input: "Hi"
Output: "len = 3"
"string = Hi"
When I input "Hi", aren't I using the previous array that has "Hello my name is Philip" stored inside. So won't I expect the array to look like:
['H', 'i', '\n', '\0', 'o', ' ', 'm', 'y', ' ', 'n', 'a', 'm', 'e', ' ', 'i', 's', ' ', 'P', 'h', 'i', 'l', 'i', 'p', '\n', '\0', etc...]
Edit:
Just to clarify, I understand how printf("%s", input) is printing the correct string. I also understand getLength will return the correct length every time.
I'm just confused about the chars saved in the array input. If we are referencing this same array in memory, how are old chars being handled?
How is the old input erased? Aren't I referencing the exact same array
that previously stored the previous input?
The old input is not erased. In each iteration of the loop, you are just overwriting the same array input and is freshly zero terminated (s[i] = '\0';) by getLength() in each iteration.
Since you are printing the string before the next iteration, it makes it possible to reuse the same array (and overwrite it). So, there really isn't any need to "save" anything.
C arrays are pointers to memory. With the line char input[MAXLINE]; you have allocated a contiguous block of 1000 bytes. Which are not going to be initialized every time unless you do so explicitly. The junk data you refer to is simply the previous iterations of using this block of bytes.
The end of a char array as a string is usually indicated by the '\0' character. Libraries that use string i/o like stdio.h make this assumption and calculate length by traversing the string until the zero character is encountered. One possible danger exists when you write nonzero characters all the way to the end of your array and then use strlen from stdio.h to find the length of your string. The function will go beyond the end of the buffer and crash your program.
I want to assign the first two values from the hash array to the salt array.
char hash[] = {"HAodcdZseTJTc"};
char salt[] = {hash[0], hash[1]};
printf("%s", salt);
However, when I attempt this, the first two values are assigned and then all thirteen values are also assigned to the salt array. So my output here is not:
HA
but instead:
HAHAodcdZseTJTC
salt is not null-terminated. Try:
char salt[] = {hash[0], hash[1], '\0'};
Since you are adding just two characters to the salt array and you are not adding the '\0' terminator.
Passing a non nul terminated array as a parameter to printf() with a "%s" specifier, causes undefined behavior, in your case it prints hash in my case
HA#
was printed.
Strings in c use a special convetion to know where they end, a non printable special character '\0' is appended at the end of a sequence of non-'\0' bytes, and that's how a c string is built.
For example, if you were to compute the length of a string you would do something like
size_t stringlength(const char *string)
{
size_t length;
for (length = 0 ; string[length] != '\0' ; ++length);
return length;
}
there are of course better ways of doing it, but I just want to illustrate what the significance of the terminating '\0' is.
Now that you know this, you should notice that
char string[] = {'A', 'B', 'C'};
is an array of char but it's not a string, for it to be a string, it needs a terminating '\0', so
char string[] = {'A', 'B', 'C', '\0'};
would actually be a string.
Notice that then, when you allocate space to store n characters, you need to allocate n + 1 bytes, to make room for the '\0'.
In the case of printf() it will try to consume all the bytes that the passed pointer points at, until one of them is '\0', there it would stop iterating through the bytes.
That also explains the Undefined Behavior thing, because clearly printf() would be reading out of bounds, and anything could happen, it depends on what is actually there at the memory address that does not belong the the passed data but is off bounds.
There are many functions in the standard library that expect strings, i.e. _sequences of non nul bytes, followed by a nul byte.
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.