C: Function not returning full string - c

I'm not sure if I'm just being really dumb but this function I have made should take chars from one array and selectively put them in another to remove things like spaces and punctuation. However, what returns seems to just be the first char (from the printf).
char * getWord(char *array) {
char *temp = malloc(sizeof(char) * 20);
int i= 0;
while(i < 20) {
if(validChar(array[i])) {
printf("pass 1 - %c\n", array[i]);
temp[i] = array[i];
printf("pass 2 - %c\n", temp[i]);
i=i+1;
}
else {
i=i+1;
}
}
printf("%s\n", temp);
return temp;
}
The validChar function:
bool validChar(char given) {
char a[]=". ,;:*!?'-\n\r";
for(int q = 0; q <=12; q++) {
if(given == a[q]){
return false;
}
}
return true;
}
In each "pass 2", the correct print is shown so the loop is working as intended. The thing I really don't understand is when I remove the conditional to select valid chars, the final print statment works as intended and prints the entire string.

First, you're using just one counter for both strings in getWord. You have to separate the reading of the string with i of the writting of the temp string with another counter, say j. j will only be incremented when you actually add some character to temp.
Finally, you're missing the ending '\0' of temp before the printf in getWord.

You need two counters one for each array. Counter i, which you already use for array, and a new one j which will be used for temp.
if(validChar(array[i])) {
printf("pass 1 - %c\n", array[i]);
temp[j] = array[i];
printf("pass 2 - %c\n", temp[j]);
i=i+1;
j=j+1;
}
else {
i=i+1;
}
The reason you only printed the first character is that the memory you got from malloc happened to contain bytes set to zero. The first character that got skipped in temp, contained a zero byte, since a string is zero terminated, that is all you printed out.
Technically those zero bytes were not initialized so the behavior of your code is undefined.
The code also doesn't zero terminate the string temp, after the copying is completed. Add an assignment of '\0' to temp at position j after the while loop, and change the while loop condition from 20 to 19 (or allocate one more byte), so the zero terminator won't be written out of bounds.

Related

How do you use an if else and check for last character '\0' of a string?

In C apparently strings are stored like an array with a null value or '\0' at the end. I wish to iterate over the string in a for loop and I need it to stop at '\0', not including it. I've tried many conditions for the if else and it all don't seem to work.
for example:
char patternInput[TEXTSIZE];
for(int i = 0; i<strlen(patternInput);i++)
{
if(patternInput[i]==NULL)
{
printf("\nlast character");
break;
}
else
{
printf("\n%c",patternInput[i]);
}
}
I've tried if(patternInput[i]==NULL), if(patternInput[i]==NUL),if(!patternInput[i]),if(patternInput[i]=='\0') and none of them seems to work.
If you're scanning the characters yourself, you can avoid the (redundant and somewhat expensive) strlen() call entirely, and instead use the value of patternInput[i] in the continuation-test of your for-loop:
char patternInput[TEXTSIZE] = "testing!";
for(int i = 0; patternInput[i] != '\0'; i++)
{
printf("\n%c",patternInput[i]);
}
printf("\nlast character\n");
Consider this code. This code prints 'Null character found' with position of the character. Notice the 'less than or equal to' in i<=strlen(str) in the loop invariant.
The last character at the length strlen + 1 is the '\0' character.
int i = 0;
char str[] = "Hello";
for(int i=0; i<=strlen(str); i++)
{
if(str[i]=='\0')
printf("Null character found at position %d", i);
}

Why won't this array get printed?

I'm trying to write a program to take 10 words as input from the user, then store it an array, and then print out the length of each word.
Here's my code:
#include <stdio.h>
#include <string.h>
char *words[10];
char length[10];
int i, j;
int main()
{
printf("Input ten words: \n");
for(i = 0; i < 10; i++)
{
printf("Enter element %d \n", i + 1);
scanf("%s", &words[i]);
}
for(i = 0; i < 10; i++)
printf("%c", words[i]);
for(i = j = 0; j < 10; j++)
{
length[j] = strlen(words[i]);
i++;
}
for(j = 0; j < 10; j++)
printf("%c", length[j]);
return 0;
}
It should be noted that I have no idea why the array "words" is defined as a pointer, I only do it because if I don't I get some warning about making a pointer from integer without a cast.
When I run the program what happens is, I get prompted to input the 10 elements, that much works, but then when it's supposed to print the "words" array, the program just crashes.
Also the reason I coded it like this is because later on I also need to print the longest and shortest word - so I figured it would help if I had the lengths of all the strings in their own array.
Does anyone know what's wrong here?
Thanks
With the line char *words[10], you are declaring an array of 10 pointers. However, these pointers are uninitialized, which means they are wild pointers. Dereferencing a wild pointer causes undefined behavior (i.e. the program may crash). If you want to use these pointers in a meaningful way, you must make each pointer point to a valid memory location, for example to an address returned by the function malloc or to the address of a char array.
However, probably the easiest solution to your problem is to not use pointers at all, but to instead declare a two-dimensional char array, like this:
char words[10][100];
That way, you are allocating space for 10 words of up to 100 characters each (including the null terminating character).
Beware that a buffer overflow will occur if the user enters a word longer than 99 (1 byte is required for the terminating null character). Therefore, the scanf line should be changed to the following:
scanf("%99s", words[i]);
That way, scanf will never attempt to write more than 100 bytes (including the terminating null character).
I have also removed the & in the scanf line above, because the & is not necessary, since words[i] will automatically decay to &words[i][0].
Also, as a general rule, you should verify that the return value of scanf is 1 before attempting to use the value that scanf wrote. For example, if the user triggers end of file on the input stream (for example by pressing CTRL-D on Linux or CTRL-Z on Windows), then scanf will return -1 without writing anything into words[i]. In that case, by subsequently reading from words[i], your program will cause undefined behavior.
Additionally, the line
printf("%c", words[i]);
must be changed to:
printf("%s", words[i]);
The loop
for(i = j = 0; j < 10; j++)
{
length[j] = strlen(words[i]);
i++;
}
can be simplified to:
for(i = 0; i < 10; i++)
{
length[i] = strlen(words[i]);
}
The line
printf("%c", length[j]);
should probably be changed to
printf("%hhu", length[j]);
because length[j] does not represent the ASCII code of a character, but just a number.

Printing char array with null character in the middle in C

I have noticed that when you try to print a null character in C, nothing will get printed.
printf("trying to print null\n");
printf("%c", '\0');
However, I am trying to print the characters in the following array one by one, up to the sixth character which is the null character.
char s[] = "Hello\0Bye";
int i;
for(i = 0; i < 7; i++) {
printf("%c", s[i]);
}
printf("\n");
I was expecting "Hello" to be printed, as since the sixth character is null nothing will be printed. However my output was: "HelloB".
It seems like printf skipped the null character and just went to the next character. I am not sure why the output is "HelloB" instead of "Hello".
Any insights would be really appreciated.
The construction '\0' is commonly used to represent the null character. Here
printf("%c", '\0');
it prints nothing.
And in the decalaration of s
char s[] = "Hello\0Bye";
when you print like
for(i = 0; i < 7; i++) {
printf("%c", s[i]);
}
printf() prints upto 0<7(h), 1<7(e)..5<7(nothing on console),6<7(B) iterations only and 6th charactar is B hence its prints HelloB.
I was expecting "Hello" to be printed ? For that you should rotate loop until \0 encountered. For e.g
for(i = 0; s[i] != '\0'; i++) { /* rotate upto \0 not 7 or random no of times */
printf("%c", s[i]);
}
Or even you no need to check s[i] != '\0'
for(i = 0; s[i]; i++) { /* loop terminates automatically when \0 encounters */
printf("%c", s[i]);
}
You can use below two options
1. size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
2.Iterate through each character and print it.
int i; for(i=0; i<7; i++) generates 7, not 6 iterations.
Printing \0 generates no pixels on the console (character 6) and then the 7th character (B follows).

which code is better ? and how do we understand that ? why is the final print function in the second code sometimes printing random numbers?

I am very new here .. so please excuse me if my question is really unnecessary .. but I think the answer will help me have some faith in myself ..here are two code snippets ..one i got on the website c4learn.com ..
#include<stdio.h>
int main()
{
char s1[100], s2[100];
int i;
printf("\nEnter the string :");
gets(s1);
i = 0;
while (s1[i] != '\0')
{
s2[i] = s1[i];
i++;
}
s2[i] = '\0';
printf("\nCopied String is %s ", s2);
return (0);
}
and the other i wrote myself ..
#include<stdio.h>
int main()
{
char s1[100], s2[100];
int i;
printf("\n Enter the string 1");
gets(s1);
printf("\n Enter the string2");
gets(s2);
for(i=0;i<100;i++)
{
if (s1[i]!='\0')
{
s2[i]=s1[i];
}
}
s2[i]='\0';
printf("\n Copied string is %s ", s2);
return(0);``
}
the problem is while running the code on dev c++ .. the final printf displayed is showing some random characters at the end of the string .. Can anyone help me understand that and which is code is better ? the initial question was ... HOW WILL YOU COPY ONE STRING TO ANOTHER WITHOUT USING ANY INBUILT LIBRARIES ? thank you ..
Your code is not quite right:
Why do you ask for the user input for s2 if you then overwrite it, copying s1?
The for cycle you wrote doesn't stop when s1 is over (I mean the null terminator character '\0') so you are also copying all the chars remaining in s1 after '\0'. If the chars in the array are not initialized (and that's the case for chars after '\0') they of course might result in random characters.
So answering your question, the first code is the right way to do it.
Any way if you want to use a for cycle you could do:
for (i = 0; i < 100; i++) {
s2[i] = s1[i];
if (s1[i] == '\0')
break;
}
You have to break out of the loop when you reach the null terminator character \0. The first code breaks out of the while loop while you're code continues on until i == 100 skipping over the null character. This is why its printing garbage past the original string.
This is what you should do to break out after the null character.
for (i = 0; i < 100; i++) {
s2[i] = s1[i];
if (s1[i] == '\0') break;
}
In the second block of code, after exiting the for loop, i has a value of 100. So you're putting the 0 byte at index 100.
Since an array of size 100 has indexes 0 to 99, you're writing past the end of the array. That causes undefined behavior.
When you're inside of the for loop, you need to break out after you find the null byte.
Also, both programs use gets which is unsafe because it does not perform any bounds checking and may write past the end of the array.

Compare two strings character by character in C

I have one 'simple' (I hope) question. I am actually coding some little program and I need to compare two strings, same length, but different letters like
Eagle
and
Hdjoh
I want to compare the first letter of the first string with the first letter of the second string,
the second letter of the first string with the second letter of the second string etc..
I started to do like this:
for(i=0, i<N, i++){
for(j=0, j<N, j++){
if(string1[i]==string1[j] etc.. etc..
}
}
I see clearly that it doesn't compare first letter with first letter, second with second etc..
So maybe anyone have an idea how can I do this? (Without using any functions of string.h, i want to do this ''on my own'').
Maybe its a stupid question but im still a novice in C so...
Ah and the last thing, I define the two strings with 5 characters in my example, but it could be more than 5 vs 5..
Thanks by advance for the ideas.
Edit 1 :
#include <stdio.h>
#define N 20
int main()
{
unsigned char string1[N], string2[N];
int Answer=0, i=0;
scanf("%s", string1);
scanf("%s", string2);
for(i=0; i<N; i++){
if(string1[i]==string2[i]){
Answer=1;
}
else{
Answer=0;
}
}
printf("Answer = %d", Answer);
return 0;
}
Why are you using a nested for loop for this? If both strings are of size n do this:
for(int i=0;i<n;i++){
if(string1[i]==string2[i]){
//do something
else if(// lesser than condition)
//do something else
else if(//greater than condition)
//do something else other than the previous something
}
Here you when i=0, you are comparing string1[0] with string2[0], when i=1, you compare string1[1] with string2[1] and so on.....
Your approach with nested loops isn't very well thought-out.
Clearly it will compare all letters of the second string against the first letter of the first string, then do the same for the second letter of the first string, and so on. Not at all the desired behavior.
Re-implementing strcmp() isn't very hard, here's a shot:
int my_strcmp(const char *a, const char *b)
{
for(; *a && *b && *a == *b; ++a, ++b)
;
if(*a < *b)
return -1;
return *a > *b;
}
Note that it returns zero when the strings are equal. A good way to write a test is:
if(my_strmcp(a, b) == 0)
{
printf("two equal strings: '%s' and '%s'\n", a, b);
}
Some people write it as if(!my_strcmp()) but I don't recommend that, since it's mashing up so many concepts.
You want to use the same index for both strings to compare:
unsigned len = strlen(s1);
assert(len == strlen(s2) && "Strings not the same length");
for (unsigned i = 0; i < len; i += 1)
{
if (s1[i] != s2[i])
return false; /* strings are not equal */
}
return true; /* strings are equal */
Make sure that the strings have the same encoding, either ASCII or UTF8 or whatever. Comparing strings of different encoding will cause trouble :)
This code compares character by character. Note that this is not suitable for crypto code as it is vulnerable to a timing attack
for(i=0; i<N; i++){
if(string1[i]==string2[i]){
equal = 1;
}else{
equal = 0;
break;
}
}
Notes:
I am assuming same length (as stated in question)
I am also assuming strings are non-zero length
Both of these assumptions may not be true in other code.
Simple compare each element until the end of string is found or a difference.
size_t i = 0;
while (string1[i] != '\0' && string1[i] == string2[j]) i++;
int StringTheSame = string1[i] == string2[j];
This ignores N, but stops when either end-of-string ('\0') is encountered.
[Edit] #Kartik_Koro suggested a concern about a timing attack. Following is a constant time solution
int diff_bits = 0;
for(size_t i=0; i<N; i++) {
diff_bits |= string1[i] ^ string2[i];
}
int equal = diff_bits == 0;
The above has a problem if either string's length is shorted than N-1, but per OP's requirements, that should not happen.

Resources