Spurious newlines+whitespace when printing substrings in C - c

I have a simple program that reads a pair of characters from a char[] array and prints each pair to the console, all on the same line - for some reason, some spurious newlines (and whitespace) are added to the output.
I've removed usage of str libs (apart from strlen) that may add newlines at the end of strings - but I am still lost as to what's happening.
The program:
#include <stdio.h>
#include <string.h>
char input[] = "aabbaabbaabbaabbaabb";
int main() {
int i;
char c[2];
size_t input_length = strlen(input);
for (i=0; i<input_length; i+=2) {
c[0] = input[i];
c[1] = input[i+1];
printf("%s", c);
}
printf("\n");
return 0;
}
Expected output:
aabbaabbabbaabbaabb
Output:
aabbaabbabb
aa
bbaabb
Why are there newlines and whitespace in the output? (Note that the 1st line has a single a towards the end - could not deduce why)
Using Apple clang version 11.0.0 (clang-1100.0.33.16), though I would doubt if that matters.

%s works properly if your string contains null character ('\0'). If it does not (just like your case), then printf function continues to print characters until it finds '\0' somewhere in memory. Remember that string in C is a character sequence terminated with '\0'. This is the reason why your code does not behave as you expected.
On the other hand, %c prints only one character so you can use:
printf("%c%c", c[0],c[1]);
If you persist in using %s, in this case you have to use %.2s. You probably already know that . shows precision in C. Precision in string means maximum number of characters that you want to print. So usage of .2 results in printing the first two characters in your string. No need to wait for '\0'!
printf("%.2s", c);
I also give #Tom Karzes's solution. You should change and add these lines:
char c[3];
c[2] = '\0';

Related

C: String erroneously printing twice

I'm playing around with C strings as in the following programme:
#include <stdio.h>
int main(void){
char *player1 = "Harry";
char player2[] = "Rosie";
char player3[6] = "Ronald";
printf("%s %s %s\n", player1, player2, player3);
return 0;
}
Which prints the following:
Harry Rosie RonaldRosie
Why is "Rosie" printing out twice?
Ronald has 6 letters, so char player3[6] leaves no space for the null-terminator character '\0'.
In your case, it printed whatever comes after Ronald in memory until a '\0' was encountered. That happened to be Rosie. You might not always be so lucky and run into an error (e.g. memory protection) before finding a '\0'.
One solution (apart from how you initialized Harry and Rosie) is to increase the number of elements by one to provide space for a trailing '\0':
char player3[7] = "Ronald";

Unexplainable behaviour when printing out strings in C

The following code works as expected and outputs ABC:
#include <stdio.h>
void printString (char toPrint [100]);
int main()
{
char hello [100];
hello[0] = 'A';
hello[1] = 'B';
hello[2] = 'C';
hello[3] = '\0';
printString(hello);
}
void printString (char toPrint [100])
{
int i = 0;
while (toPrint[i] != '\0')
{
printf("%c", toPrint[i]);
++i;
}
}
But if I remove the line that adds the null-character
hallo[3] = '\0';
I get random output like wBCÇL, ╗BCÄL, ┬BCNL etc.
Why is that so? What I expected is the loop in printString() to run forever because it doesn't run into a '\0', but what happend to 'A', 'B' and 'C'? Why do B and C still show up in the output but A is replaced by some random character?
You declaration of hello leaves it uninitialized and filled with random bytes
int main()
{
char hello [100];
...
}
If you want zero initialized array use
int main()
{
char hello [100] = {0};
...
}
There must have been, by pure chance, the value for \r somewhere in the memory cells following those of my array hello. That's why my character 'A' was overwritten.
On other machines, "ABC" was ouput as expected, followed by random characters.
Initializing the array with 0s, purposely omitted here, of course solves the problem.
edit:
I let the code print out each character in binary and toPrint[5] was indeed 00001101 which is ASCII for \r (carriage return).
When you declare an automatic like char hello [100];, the first thing to understand is that the 100 bytes can contain just about anything. You must assign values to each byte explicitly to do / have something meaningful.
You are terminating you loop when you find the \0 a.k.a the NUL character. Now, if you comment out the instruction which puts the \0 after the character c, your loop runs until you actually find \0.
Your array might contain \0 at some point or it might not. There are chances you might go beyond the 100 bytes still looking for a \0 and invoke undefined behaviour. You also invoke UB when you try to work with an unassigned piece of memory.

c function, that "uppercasing" a string

This is my target:
input: string with mixed ASCII characters (uppercase, lowercase, numbers, spaces)
output: string with only uppercase characters
I have this:
#include <stdio.h>
void csere(char s[]){
int i;
for(i=0; s[i]!='\0'; i++){
if('a'<=s[i] && s[i]<='z'){
s[i]-=32;
}
printf("%c", s[i]);
}
}
void main(){
char s[1];
scanf("%s", &s);
csere(s);
}
My problem is:
The function stops at the first 'space' character in the string.
I tried to change the s[i] != '\0' in the 'for' part for i <
strlen(s) or just for s[i], but I still get the same result.
Example: qwerty --> QWERTY, but qwe rty --> QWE
(smaller problem: The program only accepts strings with length less than 12, if i change the 1 to 0 in main function.)
Thanks for help. Sorry for bad English.
scanf only scans non-whitespace characters with the %s modifier. If you want to read everything on a string you should use fgets with stdin as the third parameter:
fgets(s, sizeof s, stdin);
If you really need to use scanf for homework or something, you should use something like:
scanf("%128[^\n]", s);
Also, take note you are not allocating enough space for the string, the fact that it has not crashed is just pure coincidence... you should allocate the space on your array:
char s[128]; // change 128 for max string size
Actually, the fgets() usage I wrote earlier would only read 1 character (including the terminator string) since you only put 1 character on the array... change the array size and it should work.
You could also just use toupper() on ctype.h, but I guess this is some kind of homework or practice.
Furthermore, if you are allowed to use pointers, this would be a shorter (and probably more performant although that'd have to be tested... compilers are good these days :-) ) way to convert to uppercase (notice though it changes your original char array, and doesn't print it, although that'd be easy to modify/add, I'll leave it to you):
void strupper(char *sptr) {
while (*sptr) {
if ((*sptr >= 'a' ) && (*sptr <= 'z')) *sptr -= 32;
sptr++;
}
}
From scanf
s
Matches a sequence of bytes that are not white-space characters. The application shall ensure that the corresponding argument is a pointer to the initial byte of an array of char, signed char, or unsigned char large enough to accept the sequence and a terminating null character code, which shall be added automatically.
This means, with %s, scanf reads a string until it encounters the first white space character. Therefore, your function converts the given string only to the first space.
To the second (smaller) problem, the array s must be large enough for the entire string given. Otherwise, you overwrite the stack space and get undefined behaviour. If you expect larger strings, you must increase the size of s, e.g.
char s[100];

How to replace a character in a string with NULL in ANSI C?

I want to replace all 'a' characters from a string in ANSI C. Here's my code:
#include <stdio.h>
#include <stdlib.h>
void sos(char *dst){
while(*dst){
if(*dst == 'a')
*dst = '\0';
dst++;
}
}
int main(void){
char str[20] = "pasternak";
sos(str);
printf("str2 = %s \n", str);
return 0;
}
When I run it, result is:
str2 = p
But it should be
str2 = psternk
It works fine with other characters like 'b' etc. I tried to assign NULL to *dst, but I got error during compile.
How can I remove 'a' characters now?
In C, strings are zero-terminated, it means that when there's a '\0' in the string it is the end of the string.
So what you're doing is spliting the string in 3 different ones:
p
stern
k
If you want to delete the a you must move all the characters after the a one position.
What printf does is: read bytes until a '\0' is found.
You transformed "pasternak" to "p\0astern\0k", so printf prints p.
This convention is used on the string functions of the stdlib so that you don't have to pass string length as an argument.
This is why it is said that in C strings are null terminated: it is just a convention followed by the C stdlib.
The downside, as you discovered, is that strings cannot contain \0.
If you really want to print a given number of bytes, use something like fwrite, which counts the number of bytes to be printed, so it can print a \0.
The answers previously provided are perfect to explain why your code does not work. But you can try to use strtok to split the string based on the 'a' characters, to then join the parts together or simply print them appart. Check this example: http://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm
'\0' is how the C language tools recognize the end of the string. In order to actually remove a character, you'll need to shift all of the subsequent characters forward.
void sos(char *dst) {
int offset = 0;
do {
while (dst[offset] == 'a') ++offset;
*dst = dst[offset];
} while (*dst++);
}

How to print a string with embedded nulls so that "(null)" is substituted for '\0'

I have a string I composed using memcpy() that (when expanded) looks like this:
char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";
I would like to print every character in the string, and if the character is null, print out "(null)" as a substitute for '\0'.
If I use a function like puts() or printf() it will just end at the first null and print out
AAAA
So how can I get it to print out the actual word "(null)" without it interpreting it as the end of the string?
You have to do that mapping yourself. If you want to, that is. In C, strings are null-terminated. So, if you use a formatted output function such as printf or puts and ask it to print a string (via the format specifier %s) it'd stop printing str as soon as it hits the first null. There is no null word in C. If you know exactly how many characters you have in str you might as well loop over them and print the characters out individually, substituting the 0 by your chosen mnemonic.
The draft says 7.21.6.1/8:
p The argument shall be a pointer to void. The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner.
However, the following:
$ cat null.c
#include <stdio.h>
int main() {
printf("%p\n", (void *)0);
}
produces:
00000000
on both gcc 4.6 and clang 3.2.
However, on digging deeper:
$ cat null.c
#include <stdio.h>
int main() {
printf("%s\n", (void *)0);
}
does indeed produce the desired output:
(null)
on both gcc and clang.
Note that the standard does not mandate this:
s If no l length modifier is present, the argument shall be a pointer
to the initial element of an array of character type.280) Characters
from the array are written up to (but not including) the terminating
null character. If the precision is specified, no more than that many
bytes are written. If the precision is not specified or is greater
than the size of the array, the array shall contain a null character.
Relying on this behavior may lead to surprises!
Instead of printing the string with %s , you will have to come up with a for loop that checks a condition whther a given char in your char array is a \0 and then print the NULL
From C++ Reference on puts() (emphasis mine):
Writes the C string pointed by str to stdout and appends a newline
character ('\n'). The function begins copying from the address
specified (str) until it reaches the terminating null character
('\0'). This final null-character is not copied to stdout.
To process data such as you have, you'll need to know the length. From there, you can simply loop across the characters:
/* ugly example */
char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";
int len = ...; /* get the len somehow or know ahead of time */
for(int i = 0; i < len; ++i) {
if('\0' == str[i]) {
printf(" (null) ");
} else {
printf(" %c ", str[i]);
}
}
One of the key cornerstones of C is strings are terminated by '\0'. Everyone lives by that rule. so I suggest you not think of your string as a string but as an array of characters.
If you traverse the array and test for '\0', you can print "(null)" out in place of the character. Here is an example. Please note, your char * str was created either as a char array or on the stack using malloc. This code needs to know the actual buffer size.
char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";
int iStrSz = <str's actual buffer size>
int idx;
for(idx=0; idx<iStrSz; idx++)
{
if('\0' == *(str + idx)
{
sprintf("%s", "(null)");
}
else
{
putchar(*(str + idx));
}
}
printf("%s", "\n");

Resources