Copy a string into another without \0 - c

I have to put a string into another without \0, I tryed a lot of ways but the string is always dirty.
char string[100];
int pos=0;
fgets(string, 99, stdin);
len = strlen(string);
printf("%d\n", len);
char array[len-1];
for(pos=0; pos<(len-1); pos++)
{
array[j]=string[pos];
j++;
}
printf("%s", string);
printf("%s", array);
In the terminal I have:
dogs dogs(ENTER)
10(ENTER)
dogs dogs(ENTER)
dogs dogs#
I also tryed to remove \0 using another symbol but it can't see '\0' or '\n', help me plz!

Passing pointer to what is not a null-terminated string to %s without length specification will invoke undefined behavior. You have to specify the length to print if you hate terminating null-character for some reason.
Try this:
#include <stdio.h>
#include <string.h>
int main(void) {
int len;
char string[100];
int pos=0;
fgets(string, 99, stdin);
len = strlen(string);
printf("%d\n", len);
char array[len];
for(pos=0; pos<len; pos++)
{
array[pos]=string[pos];
}
printf("%s", string);
printf("%*s", len, array);
return 0;
}

TL;DR You don't want null-terminator, fine. Along with that you should be ready to give up those properties, which comes with the presence of null-terminator. You can no longer make use of the array as string.
To elaborate, in your code, your array array is not null-terminated, so it cannot be used as a string. the %s format specifier expects a pointer to the null-terminated char array (in short, a string)
So, in your code,
printf("%s", array);
invokes undefined behavior by going past the allocated memory in search of the null-terminator.
You can however, print it element by element using a for loop.

To copy without the terminating null, use
memcpy( myCharArray, string, strlen(string) );
(assumes size of myCharArray is sucfficient). To print out the result, you need to use a loop instead of printf.

Related

Taking multiple strings through scanf

When I try to use scanf() to read one string of chars, everything works.
In the code below, I read two strings of chars, but if I input "abcde abcde" (arbitrary letters), printf() prints " is your character".
int main(){
char A[5], B[5];
scanf("%s %s", A,B);
printf("%c is your character", A[0]);
}
What am I doing wrong?
You are typing one string of length 5 (+1 with \0) and try to put it in a char table of size 5, which is an undefined behavior.
If you want to put “abcde” in both A and B, you need to increase the size of A and B to at least 6.
As #pmg pointed out already, the char array has to be long enough to have the null-terminator at the end of it, thus abcde abcde doesn't work, but abcd abcd works. If you would like to solve this statically, literally just stretch the size of the array buy how much you need:
char A[40], B[40];
However, if you really insist on getting dynamic allocation, you could use getline(), then malloc on some char* of the length of your input string (worst case scenario), and then use sscanf to split your input stringo to A and B.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* I = NULL;
char* A;
char* B;
size_t len = 0;
if (getline(&I, &len, stdin) != EOF)
{
A = (char*)malloc(len + 1);
B = (char*)malloc(len + 1);
sscanf(I, "%s %s", A, B);
printf("%c is your character", A[0]);
free(A);
free(B);
}
free(I);
return 0;
}

Print a string of a given length

printf("%s", ...) assumes null-terminated string. If I have a string deliminated by a length, what is the best way to do?
Suppose buf is the start address of the string, n is the length of the string. I have the following code. Is it the best way to do so?
for(int i=0;i<n;++i) {
fputc(buf[i], stdout);
}
You can use %.*s format specifier to specify the length to print.
#include <stdio.h>
int main(void) {
int length = 3;
const char* str = "123456";
printf("%.*s\n", length, str);
return 0;
}
This example will print 123.
Better way to print fixed-length data should be using fwrite(). printf() can do many thing, so it may be unnecessarily slow.
#include <stdio.h>
int main(void) {
int length = 3;
const char* str = "123456";
fwrite(str, sizeof(*str), length, stdout);
return 0;
}
I think using fwrite is also an overkill here a you are anyway printing a string (which is a set of char).
Instead you could just use putchar(), it writes to stdio by default.
while(i<n)
putchar(buf[i++]);

reversing a string in C

#include <stdio.h>
void reverse(int len, char s[], char b[]);
int main() {
char s[5] = "hello";
char b[5];
reverse(5, s, b);
return 0;
}
void reverse(int len, char s[], char b[]) {
int i;
for (i = 0; i < len; i++) {
b[(len - 1) - i] = s[i];
}
printf("%s : %s\n", s, b);
printf("%s", b);
}
Here is my code above in C. When I run it, it switches the string s[] to b[] but b[]also includes s[]. Can someone please thoroughly explain what I'm doing wrong? I really appreciate it.
char s[5] = "hello";
This is wrong, you need one more [6] in order to store the trailing '\0' (same for b)
It's better to omit the array size:
char s[] = "hello";
char b[sizeof(s)];
And you need b[i] = '\0'; after the for loop.
Your string buffers are too small, they must be six characters or more to hold the string "hello". Remember that strings C have a terminating '\0'-character at the end; that won't fit with space for only five characters.
Also, when reversing you never copy the terminating character.
You need b[len - 1] = '\0'; before exiting reverse().
When you pass non-terminated strings to printf()'s "%s" format, you get undefined behavior. Typically it "runs off the end" of the string, printing whatever it happens to find in memory, until it finds a character with the value 0 which causes it to stop.
The %s format specifier expects a string: An array of characters ending in a nul byte. You are not supplying that, so you are getting rubbish results. To hold a string with five characters, you need at least six chars.
every string in c is terminated by \0 which is a null character. so the array size should be enough to hold the string along with null character.
I will suggests to increase the size of array.
important :-
at the last assign b[last_index]='\0';
so that string b can be terminated by \0. otherwise it might give garbage values along with actual data while printing the string b.
In C, you just need to include
#include<string.h>
and use
strrev(a);
where a is the character array or string.
Whereas, your code can be modified too, to be written like this
#include <stdio.h>
void reverse(int len, char s[], char b[]);
int main() {
char s[5] = "hello";
char b[5];
reverse(5, s, b);
return 0;
}
void reverse(int len, char s[], char b[]) {
int i,j;
for (i = 0,j=len-1; i <=j; i++, j--) {
b[j]=a[i];
}
printf("%s : %s\n", s, b);
printf("%s", b);
}

Array "pointer" on writing the value?

I'm try to get from the user 5 strings, and store that string into a array of char string, but, when I try to use the program, the output of the program is allways the same, the last value of user have inputed...
See my code:
#include <stdio.h>
int main()
{
int i = 0;
char *s[50];
char str[50];
for(i=0;i<5;i++)
{
fgets(str, 50, stdin);
s[i] = str;
}
for(i=0;i<5;i++)
printf("%s\n ", s[i]);
}
So, How I can solve this, how I can put the value digited by the user into array, and print the values in other time ???
You need to use strcpy instead of simple assignment.
str is a memory location, all s[i] = str is doing is pointing to the same buffer that is overwritten every time you call fgets.
Something like the following will get you what you need:
#include <stdio.h>
int main()
{
int i = 0;
char s[5][50];
char str[50];
for(i=0;i<5;i++)
{
fgets(str, 50, stdin);
strcpy(s[i],str);
}
for(i=0;i<5;i++)
printf("%s\n ", s[i]);
}
You're creating a single array of characters with the following line
char str[50];
And then every pointer in your array s is pointing to that same single memory location. Everytime you call fgets, you're overwriting the string that is stored in that memory, and as such when you print out each of the strings in the s array, you're getting the same thing: the last value the user entered, which is stored in that single locally allocated block of memory.
Try allocating a new block of memory for each string you read in from the user, and then storing the new memory block's pointer in s:
char *str;
for(i=0;i<5;i++)
{
str = malloc(50);
fgets(str,50,stdin);
s[i] = str;
}
All the pointers of s point to str. So only the last input is stored.
Do:
for(i=0;i<5;i++)
{
fgets(str, 50, stdin);
s[i] = strdup(str);
}
If strdup() is not available (POSIX function) then you can implement it or use malloc() + strcpy().
for(i=0;i<5;i++)
{
fgets(str, 50, stdin);
s[i] = malloc(strlen(str) + 1);
strcpy(s[i], str);
}
And finally free() the pointers in s:
for(i=0;i<5;i++)
{
free(s[i]);
}
Note that char *s[50] only declares 50 pointers (not pointers to 50 characters!); they need to point somewhere before you can copy something to them. What about a 2-dim array of char:
char s[5][50];
and then reading into them with
fgets (s[i], 50, stdin);
Advantage: No need to mess with strdup, malloc and free.

How to iterate over a string in C?

Right now I'm trying this:
#include <stdio.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Usage: %s %s sourcecode input", argv[0], argv[1]);
}
else {
char source[] = "This is an example.";
int i;
for (i = 0; i < sizeof(source); i++) {
printf("%c", source[i]);
}
}
getchar();
return 0;
}
This does also NOT work:
char *source = "This is an example.";
int i;
for (i = 0; i < strlen(source); i++){
printf("%c", source[i]);
}
I get the error
Unhandled exception at 0x5bf714cf (msvcr100d.dll) in Test.exe: 0xC0000005: Access violation while reading at position 0x00000054.
(loosely translated from german)
So what's wrong with my code?
You want:
for (i = 0; i < strlen(source); i++) {
sizeof gives you the size of the pointer, not the string. However, it would have worked if you had declared the pointer as an array:
char source[] = "This is an example.";
but if you pass the array to function, that too will decay to a pointer. For strings it's best to always use strlen. And note what others have said about changing printf to use %c. And also, taking mmyers comments on efficiency into account, it would be better to move the call to strlen out of the loop:
int len = strlen(source);
for (i = 0; i < len; i++) {
or rewrite the loop:
for (i = 0; source[i] != 0; i++) {
One common idiom is:
char* c = source;
while (*c) putchar(*c++);
A few notes:
In C, strings are null-terminated. You iterate while the read character is not the null character.
*c++ increments c and returns the dereferenced old value of c.
printf("%s") prints a null-terminated string, not a char. This is the cause of your access violation.
Rather than use strlen as suggested above, you can just check for the NULL character:
#include <stdio.h>
int main(int argc, char *argv[])
{
const char *const pszSource = "This is an example.";
const char *pszChar = pszSource;
while (pszChar != NULL && *pszChar != '\0')
{
printf("%s", *pszChar);
++pszChar;
}
getchar();
return 0;
}
An optimized approach:
for (char character = *string; character != '\0'; character = *++string)
{
putchar(character); // Do something with character.
}
Most C strings are null-terminated, meaning that as soon as the character becomes a '\0' the loop should stop. The *++string is moving the pointer one byte, then dereferencing it, and the loop repeats.
The reason why this is more efficient than strlen() is because strlen already loops through the string to find the length, so you would effectively be looping twice (one more time than needed) with strlen().
sizeof(source) returns the number of bytes required by the pointer char*. You should replace it with strlen(source) which will be the length of the string you're trying to display.
Also, you should probably replace printf("%s",source[i]) with printf("%c",source[i]) since you're displaying a character.
sizeof() includes the terminating null character. You should use strlen() (but put the call outside the loop and save it in a variable), but that's probably not what's causing the exception.
you should use "%c", not "%s" in printf - you are printing a character, not a string.
This should work
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
char *source = "This is an example.";
int length = (int)strlen(source); //sizeof(source)=sizeof(char *) = 4 on a 32 bit implementation
for (int i = 0; i < length; i++)
{
printf("%c", source[i]);
}
}
The last index of a C-String is always the integer value 0, hence the phrase "null terminated string". Since integer 0 is the same as the Boolean value false in C, you can use that to make a simple while clause for your for loop. When it hits the last index, it will find a zero and equate that to false, ending the for loop.
for(int i = 0; string[i]; i++) { printf("Char at position %d is %c\n", i, string[i]); }
sizeof(source) is returning to you the size of a char*, not the length of the string. You should be using strlen(source), and you should move that out of the loop, or else you'll be recalculating the size of the string every loop.
By printing with the %s format modifier, printf is looking for a char*, but you're actually passing a char. You should use the %c modifier.
Just change sizeof with strlen.
Like this:
char *source = "This is an example.";
int i;
for (i = 0; i < strlen(source); i++){
printf("%c", source[i]);
}
This is 11 years old but relevant to someone who is learning C. I don't understand why we have all this discussion and disagreement about something so fundamental. A string literal in C, I.E. "Text between quotes" has an implicit null terminator after the last character. Don't let the name confuse you. The null terminator is equal to numeric 0. Its purpose is exactly what OP needs it for:
char source[] = "This is an example.";
for (int i = 0; source[i]; i++)
printf("%c", source[i]);
A char in C is an 8-bit integer with the numeric ASCII value of the corresponding character. That means source[i] is a positive integer until char[19], which is the null terminator after the final '.' The null character is ASCII 0. This is where the loop terminates. The loop iterates through every character with no regard for the length of the array.
Replace sizeof with strlen and it should work.
sizeof(source) returns sizeof a pointer as source is declared as char *.
Correct way to use it is strlen(source).
Next:
printf("%s",source[i]);
expects string. i.e %s expects string but you are iterating in a loop to print each character. Hence use %c.
However your way of accessing(iterating) a string using the index i is correct and hence there are no other issues in it.
You need a pointer to the first char to have an ANSI string.
printf("%s", source + i);
will do the job
Plus, of course you should have meant strlen(source), not sizeof(source).

Resources