program in c with strings - c

I have a problem with this code. I need to scan strings until I give the char 0 and count how many words with 1 char, 2, 3 ... etc. Here is my code, but it never stops.
#include <stdio.h>
#include <string.h>
int main()
{
char a[100];
int length[14],i,k;
for (i=1; i<=14; i++)
length[i]=0;
do
{
scanf("%s",a);
length[strlen(a)] =length[strlen(a)]+1;
} while (a!="0");
printf("Word Length\t|Number of Occurs\n");
for(i=1; i<=14; i++)
{
printf("%d\t\t|",i);
if (length[i]>=1)
for (k=1; k<=length[i]; k++)
printf("*");
printf("\n");
}
return 0;
}

You cannot check whether two strings are equal/different using ==/!= operators.
In C, string is array of characters and name of the array represents its address, so in your example, comparing a with "0" simply compares adress of array a and address of string "0" (which is probably address in the fixed area called string pool, depending on the compiler you use) which will never be the same, that's why your program enters an infinite loop.
You should use strcmp function form string.h

Related

Do strings in C language change in the middle of program execution?

I was writing the code for Bit stuffing, but I am not getting appropriate answer, when I checked the values of the input string, there was another garbage value added at the end of the string.
#include<stdio.h>
#include<string.h>
void input(char[],int);
void stuff(char ch[],int n)
{
char str1[6]="11111";
char str2[6]="00000";
printf("str1=%s\n",str1);
printf("ch=%s\n",ch);
if(!strcmp(ch,str1))
{
printf("\n111101");
}
else if(!strcmp(ch,str2))
{
printf("\n000010");
}
else
{
puts(ch);
}
}
void main()
{
int flag=0;
char ch[5];
input(ch,5);
printf("ch0=%s\n",ch); //printing the input string
for(int i=0;i<5;i++)
{
if((ch[i]!='0')&&(ch[i]!='1'))
{
flag=1;
}
}
if(flag==0)
{
puts("Entered data:");
for(int i=0;i<5;i++)
{
printf("%c",ch[i]);
}
puts("\nAfter stuffing");
printf("ch1=%s\n",ch); //getting garbage value here
stuff(ch,5);
}
else
{
printf("Enter a valid data\n");
printf("%d",flag);
}
}
void input(char ch[],int n)
{
printf("Enter 5 digits\n");
for(int i=0;i<=n;i++)
{
scanf("%c",&ch[i]);
}
}
The output of the code is as follows.
Enter 5 digits
11111
ch0=11111
Entered data:
11111
After stuffing
ch1=11111♣
str1=11111
ch=11111♣
11111♣
Process returned 0 (0x0) execution time : 4.046 s
Press any key to continue.
I am using Code blocks IDE with MINGW. The code above should compare the string entered with the given sequence and stuff the bits if all five bits are homogenous.
Your code has undefined behavior. For example you declared a character array with 5 elements in main
char ch[5];
Then you are calling the function input
input(ch,5);
Within the function you are entering 6 characters in the for loop
void input(char ch[],int n)
{
printf("Enter 5 digits\n");
for(int i=0;i<=n;i++)
{
scanf("%c",&ch[i]);
}
}
That is you are overwriting the memory outside the array.
Taking into account the program output
Enter 5 digits
11111
ch0=11111
the call of scanf
scanf("%c",&ch[i]);
also stored the new line character '\n' in the memory after the last element of the array. You should at least write
scanf(" %c",&ch[i]);
^^^^^
instead of
scanf("%c",&ch[i]);
Pay attention to the leading space in the format string. It allows to skip white space characters.
The array does not contain a string but you are trying to output it as if it contains a string
printf("ch0=%s\n",ch); //printing the input string
or to use it in calls of strcmp as for example
if(!strcmp(ch,str1))
that again invokes undefined behavior.
To output the array you could use the following format string
printf("ch0=%.*s\n", 5, ch); //printing the input string
and to compare character arrays you could use either strncmp or memcmp.
Pay attention to that according to the C Standard the function main without parameters shall be declared like
int main( void )
Lack of null-byte:
A string in C is an array of null-terminated bytes. You do not terminate ch in the input function.
strcmp does compare two strings, but it requires them to be null-terminated.
printf too requires a null-terminated string with the %s format specifier, otherwise it doesn't know when to stop printing. And your code would most probably result in a segmentation fault.
Accessing memory out of bounds:
This line:
for(int i=0;i<=n;i++)
invokes undefined behaviour because it's writing to out of bounds memory. ch has been declared to only contain 5 bytes, which must include the '\0' character.

How to count the number of distinct characters in common between two strings?

How can a program count the number of distinct characters in common between two strings?
For example, if s1="connect" and s2="rectangle", the count is being displayed as 5 but the correct answer is 4; repeating characters must be counted only once.
How can I modify this code so that the count is correct?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i,j,count=0;
char s1[100],s2[100];
scanf("%s",s1);//string 1 is inputted
scanf("%s",s2);//string 2 is taken as input
for(i=1;i<strlen(s1);i++)
{
for(j=1;j<strlen(s2);j++)
{
if(s1[i]==s2[j])//compare each char of both the strings to find common letters
{
count++;//count the common letters
break;
}
}
}
printf("%d",count);//display the count
}
The program is to take two strings as input and display the count of the common characters in those strings. Please let me know what's the problem with this code.
If repeating characters must be ignored, the program must 'remember' the character which were already encountered. You could do this by storing the characters which were processed into a character array and then consult this array while processing the other characters.
You could use a counter variable to keep track of the number of common characters like
int ctr=0;
char s1[100]="connect", s2[100]="rectangle", t[100]="";
Here, t is the character array where the examined characters will be stored. Its size is made to be same as the size of the largest of the other 2 character arrays.
Now use a loop like
for(int i=0; s1[i]; ++i)
{
if(strchr(t, s1[i])==NULL && strchr(s2, s1[i])!=NULL)
{
t[ctr++]=s1[i];
t[ctr]=0;
}
}
t initially has an empty string. Characters which were previously absent in t are added to it via the body of the loop which will be executed only if the character being examined (ie, s1[i]) is not in t but is present in the other string (ie, s2).
strchr() is a function with a prototype
char *strchr( const char *str, int c );
strchr() finds the first occurrence of c in the string pointed to by str. It returns NULL if c is not present in str.
Your usage of scanf() may cause trouble.
Use
scanf("%99s",s1);
(where 99 is one less than the size of the array s1) instead of
scanf("%s",s1);
to prevent overflow problems. And check the return value of scanf() and see if it's 1. scanf() returns the number of successful assignment that it made.
Or use fgets() to read the string.
Read this post to see more about this.
And note that array indexing starts from 0. So in your loops, the first character of the strings are not checked.
So it should've been something like
for(i=0;i<strlen(s1);i++)
instead of
for(i=1;i<strlen(s1);i++)
Here's a solution that avoids quadratic O(N²) or cubic O(N³) time algorithms — it is linear time, requiring one access to each character in each of the input strings. The code uses a pair of constant strings rather than demanding user input; an alternative might take two arguments from the command line and compare those.
#include <limits.h>
#include <stdio.h>
int main(void)
{
int count = 0;
char bytes[UCHAR_MAX + 1] = { 0 };
char s1[100] = "connect";
char s2[100] = "rectangle";
for (int i = 0; s1[i] != '\0'; i++)
bytes[(unsigned char)s1[i]] = 1;
for (int j = 0; s2[j] != '\0'; j++)
{
int k = (unsigned char)s2[j];
if (bytes[k] == 1)
{
bytes[k] = 0;
count++;
}
}
printf("%d\n",count);
return 0;
}
The first loop records which characters are present in s1 by setting an appropriate element of the bytes array to 1. It doesn't matter whether there are repeated characters in the string.
The second loop detects when a character in s2 was in s1 and has not been seen before in s2, and then both increments count and marks the character as 'no longer relevant' by setting the entry in bytes back to 0.
At the end, it prints the count — 4 (with a newline at the end).
The use of (unsigned char) casts is necessary in case the plain char type on the platform is a signed type and any of the bytes in the input strings are in the range 0x80..0xFF (equivalent to -128..-1 if the char type is signed). Using negative subscripts would not lead to happiness. The code does also assume that you're working with a single-byte code set, not a multi-byte code set (such as UTF-8). Counts will be off if you are dealing with multi-byte characters.
The code in the question is at minimum a quadratic algorithm because for each character in s1, it could step through all the characters in s2 only to find that it doesn't occur. That alone requires O(N²) time. Both loops also use a condition based on strlen(s1) or strlen(s2), and if the optimizer does not recognize that the value returned is the same each time, then the code could scan each string on each iteration of each loop.
Similarly, the code in the other two answers as I type (Answer 1 and Answer 2) are also quadratic or worse because of their loop structures.
At the scale of 100 characters in each string, you probably won't readily spot the difference, especially not in a single iteration of the counting. If the strings were bigger — thousands or millions of bytes — and the counts were performed repeatedly, then the difference between the linear and quadratic (or worse) algorithms would be much bigger and more easily detected.
I've also played marginally fast'n'loose with the Big-O notation. I'm assuming that N is the size of the strings, and they're sufficiently similar in size that treating N₁ (the length of s1) as approximately equal to N₂ (the length of s2) isn't going to be a major problem. The 'quadratic' algorithms might be more formally expressed as O(N₁•N₂) whereas the linear algorithm is O(N₁+N₂).
Based on what you expect as output you should keep track which char you used from the second string. You can achieve this as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i, j, count = 0, skeep;
char s1[100], s2[100], s2Used[100]{0};
scanf("%s", s1); //string 1 is inputted
scanf("%s", s2); //string 2 is taken as input
for (i = 0; i<strlen(s1); i++)
{
skeep = 0;
for (j = 0; j < i; j++)
{
if (s1[j] == s1[i])
{
skeep = 1;
break;
}
}
if (skeep)
continue;
for (j = 0; j<strlen(s2); j++)
{
if (s1[i] == s2[j] && s2Used[j] == 0) //compare each char of both the strings to find common letters
{
//printf("%c\n", s1[i]);
s2Used[j] = 1;
count++;//count the common letters
break;
}
}
}
printf("%d", count);//display the count
}

C Array First Input "\0"

The arrays [a] and [b] are supposed to take in 4 numbers each on two separate lines, and output ?A?B, as in the famous number guessing game. (For instance, 1234\n1347 should output 1A2B.) However, I found out that the 1 at a[0] gets replaced by \0 while the others are still fine. (Side-note: This happened on XCode, but not on Visual Studio.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char a[4], b[4];
int i, j;
int A = 0, B = 0;
scanf("%s%s",a,b);
for(i=0;i<4;i++)
if(a[i] == b[i])
A++;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(a[i] == b[j])
B++;
B = B-A;
printf("%dA%dB\n",A,B);
return 0;
}
Changing the arrays to size [5] solves the problem, but I want to understand what's going on. Thanks!
Strings in C are really called null terminated byte strings. That name gives a hint that there is a special terminator for the strings, which is the '\0' character.
A string of four characters needs space for five characters, with the fifth being the null terminator.
When you input four characters with your scanf call, the function will write the fifth (the terminator) out of bounds. And writing out of bounds leads to undefined behavior.

C: Replacing a substring within a string using loops

I am struggling with the concept of replacing substrings within strings. This particular exercise does not want you to use built in functions from <string.h> or <strings.h>.
Given the string made up of two lines below:
"Mr. Fay, is this going to be a battle of wits?"
"If it is," was the indifferent retort, "you have come unarmed!"
I have to replace a substring with another string.
This is what I have so far, and I'm having trouble copying the substring to a new array, and replacing the substring with the new string:
#include <stdio.h>
#include <string.h>
int dynamic();
int main()
{
char str[]="\n\"Mr. Fay, is this going to be a battle of wits?\" \n\"If it is,\" was the indifferent retort, \"you have come unarmed!\"";
int i, j=0, k=0, l=0, n=0;
unsigned int e = n-2;
char data[150];
char newData[150];
char newStr[150];
printf("Give me a substring from the string");
gets(data);
printf("Give me a substring to replace it with");
gets(newData);
dynamic();
for (i=0; str[i] != '\0'; i++)
{
if (str[i] != data[j])
{
newStr[l] = str[i];
l++;
}
else if ((str[i+e] == data[j+e]) && (j<n))
{
newStr[l] = newData[j];
j++;
l++;
e--;
}
else if ((str[i+e] == data[j+e]) && (j>=n))
{
j++;
e--;
}
else
{
newStr[l] = str[i];
l++;
}
}
printf("original string is-");
for (k=0; k<n; k++)
printf("%c",str[k]);
printf("\n");
printf("modified string is-");
for(k=0; k<n; k++)
printf("%c",newStr[k]);
printf("\n");
}
int dynamic()
{
char str[]="\n\"Mr. Fay, is this going to be a battle of wits?\" \n\"If it is,\" was the indifferent retort, \"you have come unarmed!\"";
int i, n=0;
for (i=0; str[i] != '\0'; i++)
{
n++;
}
printf("the number of characters is %d\n",n);
return (n);
}
I tried your problem and got output for my code. Here is the code-
EDIT- THIS IS THE EDITED MAIN CODE
#include <stdio.h>
#include <string.h>
int var(char *); //function declaration. I am telling CPU that I will be using this function in the later stage with one argument of type char *
int main() //main function
{
char *str="\n\"Mr. Fay, is this going to be a battle of wits?\" \n\"If it is,\" was the indifferent retort, \"you have come unarmed!\"";
int i,j=0,k=0,l=0;
char data[] = "indifferent";
char newData[] = "nonchalant";
char newStr[150];
//here 'n' is returned from the 'var' function and is received in form of r,r1,r2,r3.
int r=var(str); //getting the length of str from the function 'var' and storing in 'r'
int r1=var(data); //getting the length of data from the function 'var' and storing in 'r1'
int r2=var(newData); //getting the length of newData from the function and storing in 'r2'
unsigned int e=r1-2; //r1-2 because r1 is the data to be replaced. and string index starts from 0. Here r1 is of length 12. but we dont need to check last
//character because it is null character and the index starts from 0. not from 1. so, it is 0 to 11 and 11th is '\0'. so "12-"2"=10" characters to be compared.
for(i=0;str[i]!='\0';i++)
{
if(str[i]!=data[j])
{
newStr[l]=str[i];
l++;
}
else if((str[i+e]==data[j+e]) && (j<r2))
{
newStr[l]=newData[j];
j++;
l++;
e--;
}
else if((str[i+e]==data[j+e]) && (j>=r2))
{
j++;
e--;
}
else
{
newStr[l]=str[i];
l++;
}
}
int r3=var(newStr); //getting the length of str from the function and storing in 'r'
printf("original string is-");
for(k=0;k<r;k++)
printf("%c",str[k]);
printf("\n");
printf("modified string is-");
for(k=0;k<r3;k++)
printf("%c",newStr[k]);
printf("\n");
} // end of main function
// Below is the new function called 'var' to get the character length
//'var' is the function name and it has one parameter. I am returning integer. so, it is int var.
int var(char *stri)//common function to get length of strings and substrings
{
int i,n=0;
for(i=0;stri[i]!='\0';i++)
{
n++; //n holds the length of a string.
}
// printf("the number of characters is %d\n",n);
return (n); //returning this 'n' wherever the function is called.
}
Let me explain few parts of the code-
I have used unsigned int e, because I don't want 'e' to go negative.(I will explain more about this later).
In the first for loop, I am checking whether my string has reached the end.
In first 'IF' condn, I am checking whether the first character of string is NOT-EQUAL to the first character of the word which needs to be replaced. If condition satisfies, print regularly thr original string.
ELSE IF, i.e(first character of string is EQUAL to the first character of the word)then check the next few characters to make sure that the word matches. Here, I used 'e' because it will check the condition for str[i+e] and data[i+e]. example- ai notequalto ae. If I had not used 'e'in code,... after checking the first character itself, newdata would have been printed in newstr. I used 'e'=5 because the probabilty of 1st letter and 5th letter being the same in data and the str is less. You can use 'e'=4 also. No rule that you have to use 'e'=5 only.
Now, I am decrementing 'e' and checking whether the letters in the string is same or no. I can't increment because, there is a certain limit of size of a string. As, I used unsigned int, 'e' won't go down below 0.
ELSE, (this means that only first letter is matching, the 5th letter of str and data are not matching), print the str in newstr.
In the last FOR loop, I have used k<114 because, that much characters are there in the string. (You can write a code to find how many characters are there in a string. No need to manually count).
And lastly, I have used conditions (j<10) and (j>=10) along with ELSE-IF condition because, in first ELSE-IF, the new data is ofsize 10. So, even if the word to be replaced is more than 10,say 12 for example. I don't need the extra 2 bits to be stored in new data. So, if the size is more than 10, just bypass that in the next ELSE-IF condition. Note that this 10 is the size of new word. So, it varies if your word is smaller or bigger. And , in second ELSE-IF, I am not incrementing 'l'(l++) because, here, I am not putting anything in newstr. I am just bypassing it. So, I didn't increment.
I tried my best to put the code in words. If you have any doubt, you can ask again. I will be glad to help. And this code is NOT OPTIMAL. The numerical values used varies with the words/strings you use. Ofcourse, I can write a generalized code for that(to fetch the numerical values automatically from the strings). But, I didn't write that code here. This code works for your problem. You can change few variables like 'e' and ELSE-IF part and try to understand how the code works. Play with it.
EDIT-
include
int main()
{
char str[]="\n\"Mr. Fay, is this going to be a battle of wits?\" \n\"If it is,\" was the indifferent retort, \"you have come unarmed!\"";// I took this as string. The string which u need to calculate the length, You have to pass that as the function parameter.
int i,n=0;
for(i=0;str[i]!='\0';i++)
{
n++;
}
printf("the number of characters is %d\n",n);
return (n);
}// If you execute this as a separate program, you will get the number of characters in the string. Basically, you just have to modify this code to act as a separate function and when calling the function, you have to pass correct arguments.
//Use Pointers in the function to pass arguments.

Is it possible to get the number of elements currently stored in an array in C?

I know it's possible to use the sizeof function to get the size, but it doesn't get a true count of the array length. If I set an array of int 50 and I stored only 10 numbers in there, I would want to get 10 as the number of elements, but of course that won't happen. I know this is definitely a trivial question, but bear with me here and help me on this if it is possible.
My code so far takes an entire sentence and stores it in an array.
#include <stdio.h>
#include <string.h>
int main()
{
int i=0;
char array[50]={0};
fgets(array, 50, stdin);
int len = sizeof(array); // it doesn't work :((((((
for(i=0; i<len; i++)
{
printf("%c\n", array[i]);
}
return 0;
}
As you guys can see, if the user decides to only enter a word of lets say "Bobby Foo" then I would want len number of 9 including the space, but the sizeof function only gets length of the size of the array declared which is 50.. >.>..
Q: Is it possible to get the number of elements currently stored in an array in C?
Short answer: No. You need to track this information yourself.
You happen to be using fgets() with a character array. Since in this case you're getting a C "string", you can use the C function strlen().
It's worth noting that fgets() will also return a newline - so your string might be a one (Mac, Linux) or two (DOS/Windows) characters longer than you expect.
PS:
Here is a bit more about C strings, including the concept of "null termination" (if you're not already familiar with them):
http://www.cprogramming.com/tutorial/c/lesson9.html
Use strlen to get the size of the array. You need to include string.h.
sizeof() is not a function it is an operator. When sizeof is applied to the name of a static array (not allocated through malloc), the result is the size in bytes of the whole array.
If you are using fgets, then you need to remove \n from the string. A simple way would be:
array[strlen(array) - 1] = '\0';
A quick example:
#include <stdio.h>
#include <string.h>
#include <stddef.h>
int main()
{
int i=0;
char array[50]={0};
char *p;
fgets(array, 50, stdin);
//Remove `\n` from the array.
if ((p=strchr(array, '\n')) != NULL)
*p = '\0';
size_t len = strlen(array); // Use strlen to find the length of string
for(i=0; i<len; i++)
{
printf("%c\n", array[i]);
}
return 0;
}

Resources