Vector char strange chars - c

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.

Related

How to make a conditional loop from "Yes, no" question by comparing String with pointer initiation? [C Programming]

int main(int argc, char* argv[]) {
char* string; //local variable for a character
string = (char*)malloc(sizeof(char));
char* yes = "yes";
printf("Do you want to play (y/n)?");
scanf_s("%s", string);
if (strcmp(yes, string) == 0) {
printf("Hello welcome...");
}
Above is my code. Essentially, I want to make a loop asking for the user to input yes, y to continue; n, no to discontinue. But I simplify it for the sake of simple codes. The program just output the question, I press enter yes and enter then it stops.
I cant figure out a way to do it using array syntax( char string[] way, although array and malloc are basically the same) so I use pointer and malloc instead.
I'm going mad because this is bugging me so much. The practice assignment only asks to input character 'y' 'n' using %c but i want to do it the %s.
Really appreciate any help, im really stuck now. Thank you so much
Your code has two significant problems. First, if you want to input a string of characters, your malloc call needs to allocate space for more than one character; you should allocate the maximum number of characters you think the user's input will contain plus one - strings in C have a zero (nul) character at the end, to mark the end of the string).
Second, when you use the scanf_s function to read in a string (using the %s format specifier, as you have done), then you need to add additional parameters (the size of the target string buffer) after each string argument.
Here's a modified version of your code with these (and a few other) corrections:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
char* string = malloc(5); //local variable for a character string (up to 5 chars)
char* yes = "yes";
printf("Do you want to play (y/n)?");
scanf_s("%s", string, 5);
if (strcmp(yes, string) == 0) {
printf("Hello welcome...");
}
free(string); // Don't forget to release the memory!
return 0; // Conventionally, return 0 for success or non-zero on error
}
Note 1: Each and every call to malloc (or calloc) should be paired with a call to free to release the allocated memory, or you will end up with memory leaks.
Note 2: Please read this post: Do I cast the result of malloc?
Note 3: Although most (all?) C compilers will not insist on it, it is good practice to explicitly add a return 0; (for success) statement at the end of the main function.
Please feel free to ask for any further clarification and/or explanation.

Allocating string with malloc

I'm new in programming in C and now I'm studying strings.
My question is: if I allocate a string using malloc (as in the code below), is the NULL character automatically inserted at the end of the string?
I find an answer in another question here, and it seems that the NULL character is not automatically included.
But here comes the problem: I know functions like strlen don't work if there isn't the NULL character, and in this code I use it and it works. So I think there is \0 at the end of my string, even if I don't write it anywhere.
What's the answer?
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv) {
char *stringa1;
int n;
int i;
printf("How many characters in the string? ");
scanf("%d", &n);
stringa1 = (char*) malloc(n*sizeof(char));
printf("Insert the string: ");
scanf("%s", stringa1);
free(stringa1);
return 0;
}
malloc() returns a void* pointer to a block of memory stored in the heap. Allocating with malloc() does not initialize any string, only space waiting to be occupied.To add a null-terminating character, you either have to do this yourself, or use a function like scanf(), which adds this character for you. Having said this, you need to allocate space for this \0 character beforehand.
Your malloc() call should be this instead:
stringa1 = (char*) malloc((n+1)*sizeof(char)); /*+1 for '\0' character */
Note: You don't need to cast return of malloc. For more information, read this.
Another thing to point out is sizeof(char) is 1, so multiplying this in your malloc() call is not necessary.
You also need to check if malloc() returns NULL. This can be done like this:
if (stringa1 == NULL) {
/* handle exit */
Also, you can only use strlen() on a null-terminated string, otherwise this ends up being undefined behaviour.
Once scanf() is called, and the stringa1 contains some characters, you can call strlen() on it.
Additionally, checking return of scanf() is also a good idea. You can check it like this:
if (scanf("%d", &n) != 1) {
/* handle exit */
Your code with these changes:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char *stringa1 = NULL;
size_t n, slen;
printf("How many characters in the string? ");
if (scanf("%zu", &n) != 1) {
printf("Invalid input\n");
exit(EXIT_FAILURE);
}
stringa1 = malloc(n+1);
if (stringa1 == NULL) {
printf("Cannot allocate %zu bytes for string\n", n+1);
exit(EXIT_FAILURE);
}
printf("Insert the string: ");
scanf("%s", stringa1);
slen = strlen(stringa1);
printf("String: %s Length: %zu\n", stringa1, slen);
free(stringa1);
stringa1 = NULL;
return 0;
}
if I allocate a string using malloc (as in the code below), is the NULL character automatically inserted at the end of the string?
No. malloc() returns a block of uninitialized memory.
I know functions like 'strlen' don't work if there isn't the NULL character, and in this code I use it and it works. So I think there is '\0' at the end of my string, even if I don't wrote it nowhere.
scanf() inserts the null byte ('\0') for you when you use %s format specifier (assuming scanf() succeeded).
From man scanf():
s Matches a sequence of non-white-space characters; the next
pointer must be a pointer to the initial element of a
character array that is long enough to hold the input sequence
and the terminating null byte ('\0'), which is added
automatically. The input string stops at white space or at
the maximum field width, whichever occurs first.
(emphasis mine).
By the way, you should do error checking for scanf() and malloc() calls.
malloc returns pointer to an uninitialized memory extent.
If you want that the memory extent would be initialized by zeroes then you can use another standard function calloc instead of malloc.
Take into account that usually such a question like this
printf("How many characters in the string? ");
imply that the terminating zero is not counted. So you have to allocate one more byte of memory. For example
stringa1 = ( char* )malloc( ( n + 1 ) *sizeof( char ) );
or
stringa1 = ( char* )calloc( n + 1, sizeof( char ) );
In the last case you may apply the function strlen which returns 0 because the memory extent is zero-initialized.
This call of scanf
scanf("%s", stringa1);
is unsafe. It is better to use fgets instead. For example
fgets( stringa1, n + 1, stdin );
This function can append the string with the new line character. To remove it from the string you can write
stringa1[strcspn( stringa1, "\n" )] = '\0';
The definition of "string" in C is a sequence of characters, terminated by a null character.
To allocate memory for a string, count the chracters (e.g. strlen) and add 1 for this terminating null character.
Functions like scanf and strcpy add the null character; a function like strncpy doesn't always do that.
The easy way to achieve this is to include cs50 library.
Just use get_string function:
#include <stdio.h>
#include <cs50.h>
int main(void) {
// input the string to stringa1
char *stringa1 = get_string("Insert the string: ");
// call the string
printf("The string you type was: %s\n", stringa1);
return 0;
}
Sample output:
Insert the string: Hello World, I am newbie!
The string you type was: Hello World, I am newbie!

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.

lack of understanding about sscanf usage

I would like to parse a specific line. So, I wrote the following piece of code in order to test the logic but I probably understand something wrongly :
typedef struct vers
{
char tu8UVersion[5];
char tu8UCommit[32];
}tst_prg_versions;
int main(int argc, char **argv)
{
tst_prg_versions lstVer;
char buf1[32];
char buf2[32];
char str[] = "BOARD-VERS-v1.0.0-git+9abc12345a";
sscanf(str, "BOARD-VERS-v%5s-git+%s", lstVer.tu8UVersion, lstVer.tu8UCommit);
printf("vers='%s'\n", lstVer.tu8UVersion);
printf("commit='%s'\n", lstVer.tu8UCommit);
sscanf(str, "BOARD-VERS-v%5s-git+%s", buf1, buf2);
printf("vers='%s'\n", buf1);
printf("commit='%s'\n", buf2);
return 0;
}
Once executed it returns :
vers='1.0.09abc12345a'
commit='9abc12345a'
vers='1.0.0'
commit='9abc12345a
Why the first vers is equals to 1.0.09abc12345a and not 1.0.0 ?
The first actually reads 1.0.0! Problem is, however, that tu8UVersion is not null-terminated, thus printf (not sscanf) prints beyound the field (doing so is undefined behaviour, however, as noted by sjsam) - which is immediately followed by tu8UCommit (does not necessarily have to be so, there could still be some fill bytes in between for alignment reasons!).
You need to either print 5 characters at most (%.5s in printf format string) or leave place for terminating the tu8UVersion with 0, as proposed in a comment already.
Something similar could have happened with your buffers, too. You are lucky that they appearently have been initialized to 0 already (probably because of compiled as debug version), which again does not necessarily have to happen. So with bad luck, you could have printed the whole rest of buf1 (having been left at garbage) and even beyond.
Why the first vers is equals to 1.0.09abc12345a and not 1.0.0 ?
Remember that you have
typedef struct vers
{
char tu8UVersion[5];
char tu8UCommit[32];
}tst_prg_versions;
I guess, there is a good chance the memory for tu8UVersion and tu8UCommit is contiguous. Since you have not null-terminated tu8UVersion when you do :
printf("vers='%s'\n", lstVer.tu8UVersion);
it goes on to print tu8UCommit and it stops because tu8UCommit is null terminated.
While sscanf seem the most sensible solution here you could also introduce some formatting :
char tu8UVersion[32];
/* version number can't get too big.
* So the first step is do allocated a
* reasonably - but not too - big size for it.
* So that you can be sure there are few empty bytes at the end.
*/
and then use a function to sanitize a string :
char* sanitized(char* ptr)
{
if(ptr[strlen(ptr)]!='\0') // include string.h for strlen
ptr[strlen(ptr)]='\0';
return ptr;
}
and print it like :
printf("vers='%s'\n", sanitized(lstVer.tu8UVersion));
Your problem has already been identified in the comments: You don't leave space for the terminating null character and the two strings are run together.
If you want to scan a version whose size you don't know beforehand, you can limit the characters to scan to decimal digits and points with %[.-9] or to everything except a hyphen with %[^-]. (The %[...] format is like %s, except that you must provide a list of valid characters in the brackets. A caret as first letter means that the string is made up of characters that are not listed. In other words, %s is short for %[^ \t\n]
When you scan a string, you should test the return value of sscanf to be sure that all items have been scanned correctly and contain valid values.
Here's a variant that scans version numbers of up to 11 letters:
#include <stdlib.h>
#include <stdio.h>
typedef struct vers
{
char tu8UVersion[12];
char tu8UCommit[32];
} tst_prg_versions;
int main(int argc, char **argv)
{
tst_prg_versions lstVer;
char str[] = "BOARD-VERS-v1.0.0-git+9abc12345a";
int n;
n = sscanf(str, "BOARD-VERS-v%11[^-]-git+%s",
lstVer.tu8UVersion, lstVer.tu8UCommit);
if (n == 2) {
printf("vers='%s'\n", lstVer.tu8UVersion);
printf("commit='%s'\n", lstVer.tu8UCommit);
} else {
puts("Parse error.");
}
return 0;
}

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