clear the last 5 characters from a string using memset - c

I have to clear the last 5 characters from a string using memset in c;
I know only to set the first characters from a string using this function.
For example:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "almost every programmer should know memset!";
memset (str,'-',6);
puts (str);
return 0;
}
Thank you!

Use:
char str[] = "EVERY C programmer should know memset!";
memset (&str[strlen(str) - 5],'-',5);
This will overwrite the last 5 characters with -.
Beware that the string hast to have at least 5 characters for this to work correctly.

Related

bzero doesn't do what it says it does

I use vscode as my code editor, and in the header file <strings.h> there is a function called bzero and when hovering on the function vscode says that bzero Set N bytes of S to 0. But I don't think it works like that. I created an array of 11 chars which called s and placed inside it Hello World.
Then I used bzero to set the first 4 bytes of s to 0, but from the output it seems like it cleaned the whole buffer.
#include <strings.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
char s[11] = "Hello World";
bzero(s, 4);
puts(s);
return 0;
}
$ cc main.c -o main && ./main
# empty
$
bzero does exactly what it says. The issue you’re facing is due to a misunderstanding of what a string is in C.
Briefly, a C string is a zero-terminated buffer of chars. That is, C treats an array of chars as a string by considering all chars until it finds the first one whose value is 0.
puts (and printf etc.) uses this definition of “string”.
As a consequence, setting even just the first char in the array to 0 results in an empty string, regardless of what comes after.
(Note also that bzero is a legacy function and its use is discouraged; use memset instead.)
Zero is a string-terminating character. Therefore if you set the first byte of your string to zero, puts will believe that the string is empty.
puts() expects a pointer to a string. Strings in C is sequences of characters *terminated by a null-character ('\0'). Null-character is represented by a value zero.
Therefore, puts() stops at the first zero and prints an empty string.
Print the whole buffer to see the effect of bzero().
#include <strings.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
char s[11] = "Hello World";
bzero(s, 4);
for (int i = 0; i < 11; i++) printf("%d ", s[i]); // print elements of the buffer
puts(s);
return 0;
}
Output:
0 0 0 0 111 32 87 111 114 108 100

Vector char strange chars

Anyone know how to copy to strings? Cause I used the function strcpy but when I print the result it show strange characters. I want to concatenate 'name' + '#' + 'e-mail'. With scanf I have to put the character null '\0'?
#include <stdio.h>
#include <string.h>
int main (){
char message[150];
char name[150];
char mail[150];
char result[150];
printf("Introduce name: \n");
scanf("%s",message);
printf("Introduce email \n");
scanf("%s",server);
strcpy(result,message);
result[strlen(result)]='#';
strcpy(&result[strlen(result)],server);
printf("RESULT: %s\n",result);
return 0;
}
result[strlen(result)]='#'; overwrites the NUL terminator introduced into result by strcpy(result,message);. So the result of a subsequent strlen is undefined.
A better solution is to use strncat, or you could get away with writing
char result[150] = {'\0'};
which will initialise the entire array.
But you still run the risk of overflowing your result array. You could use the safer strncpy to obviate that. Better still, use snprintf and have the C standard library perform the concatenation for you.

unexpected results on simple string reverse algorithm

I'm relatively new to C. I wanted to lern the language a bit by solving coderbyte challenges.
But I'm stucked at the first. It is supposed to be a simple String reverse algorithm.
When I input things like "asdf" or "1234567" the output is correct ("fdsa", "7654321"). But when I type "12345678" or "thisiscool" I get "87654321▒#"/"loocsisiht#" as a result. I don't know where the # are comming from.
This is my code:
#include <stdio.h>
#include <string.h>
void FirstReverse(char str[]) {
int len = strlen(str);
char nstr[len];
int i;
for(i = 0; i < len; i++) {
nstr[i] = *(str+len-1-i);
}
printf("%s\n", nstr);
}
int main(void) {
char str[100];
FirstReverse(gets(str));
return 0;
}
Can someone please tell me where I can find the error?
Thanks in advance :)
In C, strings are zero-terminated. A string "cat", for example, has 4 characters, and is represented as ('c','a','t',(char)0). You forgot about the final 0.
Note that strlen returns the string length without the final 0, so a string foo contains strlen(foo)+1 characters. Remember this when you allocate strings.
As the other answers have mentioned, you're missing a terminator.
It should also be noted that it's bad practice to allocate strings the way you did. An array should always have a fixed size if you create it that way.
You should instead do:
char * nstr = malloc(sizeof(char) * (len+1));
Thereby allocating the size of each character (1 byte) times the lenght.
Note the +1 because you need room for the string terminator.
When you call printf(, string); , it's gonna start from the first letter and print everything up to the terminator. Since you have no terminator here, it prints random characters, such as #.
What you're gonna wanna do to fix that, is adding:
nstr[i] = '\0';
after your loop.
Also remember to free the allocated memory.
You forgot to allocate a char for the terminating '\0' in nstr[].
So, better use: char nstr[len + 1]; and set nstr[len] = 0;
Furthermore: gets() is evil: from the glibc manual page:
Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.

Why is strncpy in my for loop uneffective?

I'm trying to split a string into multiple little strings (of nb size).
But it doesn't work as i would like :
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
int main(int argc, char *argv[]) {
char *source = argv[1];
int taille=0;
int i=0;
int k;
int nb = 5;
char dest[strlen(source)/nb][nb];
while(i<strlen(source))
{
char *src = &source[i];
strncpy(dest[taille],src,nb);
i=i+nb;
taille++;
}
for(k = 0 ; k <8;k++)
{
printf("\t%s\n",dest[k]);
}
}
here is the trace :
jerome#debian:~/codeFTP/code/serveur$ ./a.out " bonjour cocoman, tu me donne20 balles?"
bonjour cocoman, tu me donne20 balles?
our cocoman, tu me donne20 balles?
ocoman, tu me donne20 balles?
n, tu me donne20 balles?
me donne20 balles?
onne20 balles?
0 balles?
les?
but the most weird is that if i take out the while ( or thefor, i've tried both), it works ( by takingoff the while i mean writing the strncpy 8 times with appropriates values instead of using loops).
Thanks for your interest.
strncpy does not null terminate strings. You'll need to do that yourself. When you printf the first one, printf never finds the null and starts printing off whatever happens to follow it in memory. Because they are in an array, the next byte it sees is the first byte of the next string. This continues until it reaches the last string, which is null terminated because strncpy actually saw the end of the source string.
You'll need to change your declaration to hold one more byte per string for the null character:
char dest[strlen(source)/nb][nb + 1];
And then manually null-terminate each substring after the copy:
dest[taile][nb] = 0;
I'm not sure why unrolling the loop worked - there was probably a slight change in your other logic when you rewrote it.
Edited to add: Also, as Gopi said in their answer, your math for finding the number of strings rounds down. If the string length ins't a perfect multiple of nb, then your array is too small and you are invoking undefined behavior. The simplest solution is to add one to that dimension too. Your loop is safe because it is based on strlen, not the number of substrings you computed.
char dest[strlen(source)/nb + 1][nb + 1];
There is a potential problem with
strlen(source)/nb as index and this will have minimum rows compared to strlen(source) and you are doing the below
while(i<strlen(source))
{
char *src = &source[i];
strncpy(dest[taille],src,nb);
i=i+nb;
taille++;
}
Now dest[taille] is bound to be array out of bound access and also make sure
strncpy() doesn't \0 terminate the strings.
Basic case : Pass some string of length less than 5 and you have UB. There are multiple such potential bugs in your code.

The basics of using strings and substrings in C programming [closed]

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've been trying to learn C programming by reading a textbook, but am confused about how strings and substrings work.
I have an idea of what strings and substrings are from java, but can't figure out the syntax in C.
Here's a question from the book that I thought might be easy, but I can't get it.
Write and test a function hydroxide that returns a 1 for true if its string argument ends in the substring OH.
It recommends testing the function with KOH and NaCl.
Also, how would I remove and add letters at the end of the string?
Like, if for some reason I wanted to change NaCl to NaOH?
Any help and explanations would be really appreciated.
ETA:
I guess what I'm most confused on is how to make the program look at the last two letters in the string and compared them to OH.
I'm also not sure how to pass strings to functions.
String is a sequence of characters that ends with special null-terminated character '\0'. If there is no \0, functions that work with string won't stop until the \0 symbol is found. This character may happen in any place after the end of pseudo string (I mean a string without \0) and only then stop.
The following example shows the necessity of this null-terminated character:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char string[] = "Hello!";
printf("original string:\n%s\n\n", string);
memset(string, '-', 5);
printf("memset doesn't affect the last two symbols: '!' and '\\0':\n%s", string);
memset(string, '-', 6);
printf("\n\nmemset doesn't affect the last symbol: '\\0':\n%s\n\n", string);
memset(string, '-', 7);
printf("memset affects all symbols including null-terminated one:\n%s", string);
return 0;
}
/* OUTPUT:
original string:
Hello!
memset doesn't affect the last two characters: '!' and '\0':
-----!
memset doesn't affect the last character: '\0':
------
memset affects all characters including null-terminated one:
-------#↓#
*/
Substring is a char sequence that is in a string. It may be less or equal to the string.
Suppose, "NaOH" is a string. Then substring may be: "N", "a", "O", "H", "Na", "aO", "OH", "NaO", "aOH", "NaOH". To find whether substring is in the string or not you can use strstr function. It's prototype is char * strstr ( char * str1, const char * str2 );.
This code shows this function's results:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *ptrCh = NULL;
ptrCh = strstr("hello", "h");
printf("ptrCh: %p\n", ptrCh);
printf("%s\n\n", ptrCh);
ptrCh = strstr("hello", "z");
printf("ptrCh: %p\n", ptrCh);
printf("%s\n\n", ptrCh);
return 0;
}
/* OUTPUT:
ptrCh: 00403024
hello
ptrCh: 00000000
(null)
*/
As for the first printf, it prints characters beginning from the position of 'h' and when it reaches null-terminated character, which is next after 'o', it stops, exactly as in previous program.
To make your program more interactive, you can declare array and then a pointer to it. Array size must be enough to store the longest formula. Suppose, 100 will be enough:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char buf[100] = {0};
char *ptr = &buf[0];
scanf("%s", ptr);
// printf() gets a pointer as argument
printf("%s\n", ptr);
// printf() gets also a pointer as argument.
// When you pass arrays name without index to a function,
// you pass a pointer to array's first element.
printf("%s", buf);
return 0;
}
And as for rewriting letters in the end of the string. Here is a small program that does it. Pay attention at comments:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char buf[100] = {0};
char formula[100] = {0};
char compound[100] = {0};
char *ptr = &buf[0];
char *pFormula = &formula[0];
char *pCompound = &compound[0];
printf("Enter formula: ");
scanf("%s", pFormula);
printf("Enter chemical compound: ");
scanf("%s", pCompound);
// Copying the first chemical elements without the last
// several that will be replaced by another elements.
strncpy(ptr, pFormula, strlen(pFormula) - strlen(pCompound));
// Adding new compound to the first elements.
// Function also adds a null-terminated character to the end.
strncat(ptr, pCompound, strlen(pCompound));
printf("The new chemical compound is: ");
printf("%s", ptr);
return 0;
}
/* OUTPUT:
Enter formula: NaOH
Enter chemical compound: Cl
The new chemical compound is: NaCl
*/
In C, we use null-terminated strings. That is the "invisible", 0 value. Not ASCII "0", but the zero value, like 8-bit 0x00. You can represent it in literal text with '\0' or "\0" or unquoted 0, however, in a literal string it is redundant because most functions like strcmp() or strstr() or strcat() all expect and work with null terminated strings. Null char is the stops sign for the C standard string functions.
One easy way to implement this with C library calls is to test for existence of the substring and then test that substring's length, which verify it is at end of string.
Assume buf is some big string buffer, char buf[1024] and char *temp is a temporary variable.
temp = strstr(buf, "OH") returns the pointer to "OH" if exists in buf at any offset.
strlen(temp) Get length of temp, if at end of string, it will be 2 (doesn't include null terminator), so if the original string is "OHIO" or "SOHO" it wont match because it'll be 4 and 3 respectively.
The above is the core of the code, not the full robust implementation. You need to check for valid return values, etc.
char buf[1024];
char *temp;
strcpy(buf, "NaOH");
if((temp = strstr(buf, "OH")) != 0)
{
// At this point we know temp points to something that starts with "OH"
// Now see if it is at the end of the string
if(strlen(temp) == 2)
return true; // For C99 include stdbool.h
return false;
}
You could get obscure, and check for the null terminator directly, will be a smidge quicker. This code is safe as long as it is inside the if() for strstr(), otherwise never do this if you don't know a string is a least N characters long.
if(temp[2] == '\0')
return true; // For C99 include stdbool.h
As far as appending to a string, read the docs on strcat. Keep in mind with strcat, you must have enough space already in the buffer you are appending into. It isn't like C++ std::string or Java/C# string where those will dynamically resize as needed. In C, you get to do all of that yourself.

Resources