I wrote the following function and when I run it , it produces an infinite loop and I dont understand why.
This function creates a dynamic array of dynamic strings. Every such string starts with a letter given, or with a capital letter which is compatible to the letter given:
void wordsStartWithLetter(char letter, char *str,char***newstr,int *numOfWords)
{
int i=0, count=0;
char *word;
char *delimiter = " ";
while (str[i] != '\0')
{
if (str[i]==letter ||str[i]==(letter-32 )) //if it founds the letter at the begining of the word, than run till the space//
{
while (str[i] != ' ' && str[i] != '\0' )
i++; //counting the number of words beginng with the letter given//
count++;
}
else
{
while (str[i] != ' ' && str[i] != '\0' )
i++;
}
}
*newstr = (char**)malloc (sizeof(char*)*count);
*numOfWords=count;
i=0;
word = strtok(str, delimiter); //we use strtok to separate each word from the origin string//
while(word!=NULL)
{
if (word[0]==letter ||word[0]==letter-32)
{
(*newstr)[i]=word; //insert the compatible words into the new 2D-string//
i++;
}
word = strtok(NULL, delimiter);
}
}
I call that function the by the following way:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#define SIZE 50
void Ex();
void wordsStartWithLetter(char letter, char *str,char***newstr,int *numOfWords) ;
void main()
{
Ex();
}
void Ex()
{
char ch;
char str[SIZE];
char **newstr;
int numOfWords,i;
printf("please enter a string: ");
_flushall();
gets(str);
printf("plese enter a letter: " );
_flushall();
ch=_getche();
wordsStartWithLetter(ch, str,&newstr,&numOfWords);
("the words of the origin string which start which %c :\n",ch);
for(i=0;i<numOfWords;i++)
printf("%s\n",newstr[i]);
for (i=0;i<numOfWords; i++)
free(newstr[i]);
free(newstr);
}
Consider this input string "a b" and assume the letter is c.
When i is 0 you enter the code below because str[0]is a which doesn't match the letter:
else
{
while (str[i] != ' ' && str[i] != '\0' )
i++; // Increment i from 0 to 1
}
In the above block, you increment i to 1 and then leave the block because str[1] is ' '
In the next main loop, you will again hit this code block:
else
{
while (str[i] != ' ' && str[i] != '\0' )
i++; // No increment, i.e. i stays at 1
}
but you will not increment i (as str[1] is a space). In other words - i remains at 1 and you have an infinite loop.
Maybe you can fix it by this:
else
{
while (str[i] != ' ' && str[i] != '\0' )
i++; // No increment, i.e. i stays at 1
// Add this line to remove the spaces
while (str[i] == ' ') i++;
}
Related
My code works to delete any vowels and prints the first letter of the word as a capital letter.
How can I get my expected output to work?
If the value is " I am Iron Man" (with a leading space), it works and prints "M Rn Mn".
However, without the space at the beginning of the string, my output is "m Rn Mn" but
the expected output is "M Rn Mn".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char str[] = "I am Iron Man";
int i, j, len = 0;
len = strlen(str);
// Accepting input.
for (i = 0; i < len; i++) {
// Check vowels.
if (str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o' || str[i] == 'u' ||
str[i] == 'A' || str[i] == 'E' || str[i] == 'I' || str[i] == 'O' || str[i] == 'U') {
// delete vowel syntax
for (j = i; j < len; j++) {
// Store after removing vowels
str[j] = str[j + 1];
}
i--;
len--;
}
str[len + 1] = '\0';
}
for(i=0; str[i]!='\0'; i++)
{
//check first character is lowercase alphabet
if(i==0)
{
if((str[i]>='a' && str[i]<='z'))
str[i]=str[i]-32; //subtract 32 to make it capital
continue; //continue to the loop
}
if(str[i]==' ')//check space
{
//if space is found, check next character
++i;
//check letter if lowercase
if(str[i]>='a' && str[i]<='z')
{
str[i]=str[i]-32; //subtract 32 to make it capital
continue; //continue to the loop
}
}
}
printf("%s", str);
return 0;
}
Your problem lies with excessive use of the continue statement in the second for loop. The second continue is just plain pointless, as control reaches the end of the loop, anyway, after the point where you have that.
But the first continue is actually causing the fault: after removal of the vowels, the first character in the modified string will be a space – so, the first if block inside the second loop will be entered, and that will skip the check for a lowercase letter following the space.
Removing those continue statement will fix your code.
Also, note that you can use the islower and toupper functiosn to check for lowercase letters and convert to uppercase:
#include <stdio.h>
#include <string.h>
#include <ctype.h> // For islower and toupper
int main()
{
char str[] = "I am Iron Man";
size_t i, j, len = 0;
len = strlen(str);
// Accepting input.
for (i = 0; i < len; i++)
{
// Check vowels.
if (str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o' || str[i] == 'u' ||
str[i] == 'A' || str[i] == 'E' || str[i] == 'I' || str[i] == 'O' || str[i] == 'U') {
// delete vowel syntax
for (j = i; j < len; j++)
{
// Store after removing vowels
str[j] = str[j + 1];
}
i--;
len--;
}
str[len + 1] = '\0';
}
for (i = 0; str[i] != '\0'; i++)
{
//check first character is lowercase alphabet
if (i == 0)
{
if (islower(str[i])) {
str[i] = toupper(str[i]);
}
// A "continue" here is wrong ... it will skip the following check for a lowercase letter
}
if (str[i] == ' ') //check space
{
//if space is found, check next character
++i;
//check letter if lowercase
if (islower(str[i]))
{
str[i] = toupper(str[i]);
// No need for a "continue" here ... we're already at the end of the loop
}
}
}
printf("%s\n", str);
return 0;
}
I have another solution for you, that may be a bit easier to comprehend:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char str[] = "I am Iron Man";
char *in;
char *out;
int up = 1; // very simple state, if "up" then next character should be made upper
for (in = str, out = str; *in; in++) {
if (strchr("aeiouAEIOU", *in) != NULL) {
// do nothing
} else if (*in == ' ') {
*out++ = *in;
up = 1; // we see a space, so next letter should be upper
} else if (up) {
*out++ = toupper(*in);
up = 0; // we see a letter (or other character), ignore case
} else {
*out++ = *in;
}
}
*out = '\0';
printf("%s\n", str);
}
Or, if you don't like/understand the pointer syntax:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char str[] = "I am Iron Man";
int i;
int o;
int up = 1; // very simple state, if "up" then next character should be made upper
for (i = 0, o = 0; str[i]; i++) {
if (strchr("aeiouAEIOU", str[i]) != NULL) {
// do nothing
} else if (str[i] == ' ') {
str[o++] = str[i];
up = 1; // we see a space, so next letter should be upper
} else if (up) {
str[o++] = toupper(str[i]);
up = 0; // we see a letter (or other character), ignore case
} else {
str[o++] = str[i];
}
}
str[o] = '\0';
printf("%s\n", str);
}
In both cases, a very simple state is used. For more complex conditions, you should learn about state machines. In this case, the up state indicates that the next letter should be capitalised.
Note that if you want to remove leading spaces, after "removing" the vowels, you need to modify the logic a bit:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char str[] = "I am Iron Man";
char *in = str; // we initialize in and out here already
char *out = str;
int up = 1; // very simple state, if "up" then next chacter should be made upper
// we skip leading vowels AND spaces, this is a special case
while (*in && (strchr("aeiouAEIOU ", *in) != NULL)) {
in++;
}
// now we are at the first character that is not a vowel or space
for ( ; *in; in++) {
if (strchr("aeiouAEIOU", *in) != NULL) {
// do nothing
} else if (*in == ' ') {
*out++ = *in;
up = 1; // we see a space, so next letter should be upper
} else if (up) {
*out++ = toupper(*in);
up = 0; // we see a letter (or other character), ignore case
} else {
*out++ = *in;
}
}
*out = '\0';
printf("%s\n", str);
}
Well now you have a few examples to study that take a bit of a different approach. See if you understand the logic, and try to make it so that other characters like e.g. ( and ) also delimit words.
One of the problems is that you've got too much code. It iterates through the entire array once to strip out vowels, then again to adjust the case of the first letter of each word. Imagine this is processing data that is measured in Gb. A second pass is unnecessary.
(And, there are standard library functions like isalpha() and toupper() that you should use. Don't write code with "magic numbers".)
It's worth studying a program's 'flow control', without resorting to arbitrary 'continue' statements to affect that flow.
It's also worth starting from scratch with a minimal block of code in main(), then developing your algorithm in a function (or several). Avoid the tendency to have one long, linear program all inside main(). If you can put functionality into 'compartments', each can be developed and tested and forgotten about as the program grows more complex.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// A single pass "compacts" the data (no vowels) while also using some single operations
//tracking changing from one word to the next (first letter to uppercase.)
char *func( char *str ) {
for ( int d = 0, s = 0, up = 0; (str[d] = str[s]) != '\0'; s++)
if( !strchr( " aeiouAEIOU" + !!up, str[d] ) ) {
if( str[d] == ' ' )
up = 1;
else if( up++ < 2 )
up++, str[d] = (char)toupper( (unsigned char)str[d] );
d++; // 'd'estination idx only increments here!
}
return str;
}
int main(void) {
// sample test strings
char *strs[] = {
"I am Iron Man",
" I am Iron Man ",
"Iron Man am I",
" Iron Man am I",
"The man of steel",
" The man of steel",
};
for( size_t i = 0; i < sizeof strs/sizeof strs[0]; i++ )
puts( func( strs[i] ) );
return 0;
}
M Rn Mn
M Rn Mn
Rn Mn M
Rn Mn M
Th Mn F Stl
Th Mn F Stl
I have recently started learning C, and I made this small piece of code, but it's not really working the way I wanted:
#include <stdio.h>
#include <string.h>
int main()
{
int i;
char a[] = "Bill Sarah Alice";
for (i = 0; a[i] != '\0'; i++)
{
if (a[i] != '\t' || a[i] != ' ')
{
printf("%c", a[i]);
}
putchar('\n');
}
return 0;
}
I wanted to print one name per line, but instead its printing one character per line. Can someone tell how should I fix it so it will work?
if(a[i] != '\t' || a[i] != ' '){
Every character is not tab or not space. So this if will be passed by every single character. You then output a newline after every single character. So this code is equivalent to this:
for(i=0; a[i] != '\0'; i++){
printf("%c", a[i]);
putchar('\n');
}
If you want to print each name on a line, you need to do something more like this:
for(i=0; a[i] != '\0'; i++){
if(a[i] == '\t' || a[i] == ' ')
putchar('\n');
else
printf("%c", a[i]);
}
putchar('\n');
Alternatively to other answers you can use isspace to detect spaces or tabs:
#include <ctype.h> // for isspace()
#include <stdio.h>
int main()
{
int i;
char a[] = "Bill Sarah Alice";
for (i = 0; a[i] != '\0'; i++)
{
if (!isspace(a[i])) // if it's not a space
{
printf("%c", a[i]); // print character
}
else
putchar('\n'); // if it is print a newline
}
}
Output:
Bill
Sarah
Alice
There are two issues in your code. First, the newline character will be printed on every run through the for loop; to fix this, put the putchar('\n'); line into an else block.
Second, your test condition is wrong and can never be false: the character cannot be both a tab and a space, so one of the != tests will always be true; to fix this, change the || to a &&.
int main()
{
int i;
char a[] = "Bill Sarah Alice";
for (i = 0; a[i] != '\0'; i++) {
if (a[i] != '\t' && a[i] != ' ') {
printf("%c", a[i]);
}
else {
putchar('\n');
}
}
return 0;
}
Within the for loop an output of the new line character '\n' is executed after printing each character in the string that is not equal to '\t' or to ' '.
if(a[i] != '\t' || a[i] != ' '){
printf("%c", a[i]);
}
putchar('\n');
Moreover the condition in the if statement shall be written at least like
if(a[i] != '\t' && a[i] != ' '){
^^^^
You need to output the new line character after a whole name is outputted. So if you are outputting a name character by character then you need one more inner loop.
Also the header <string.h> is redundant because neither declaration from the header is used in your program. So you may remove the directive
#include <string.h>
The algorithm can look the following way as it is shown in the demonstrative program below. It is implemented as a separate function.
#include <stdio.h>
void print_names( const char *s )
{
while ( *s != '\0' )
{
while ( *s == ' ' || *s == '\t' ) ++s;
while ( *s && *s != ' ' && *s != '\t' ) putchar( *s++ );
putchar( '\n' );
}
}
int main(void)
{
char a[] = "Bill Sarah Alice";
print_names( a );
return 0;
}
The program output is
Bill
Sarah
Alice
If to include the header <ctype.h>
#include <ctype.h>
then the function can be rewritten using the standard C function isblank that itself does the check whether a character is equal to the space character or to the tab character.
#include <stdio.h>
#include <ctype.h>
void print_names( const char *s )
{
while ( *s != '\0' )
{
while ( isblank( ( unsigned char )*s ) ) ++s;
while ( *s && !isblank( ( unsigned char )*s ) ) putchar( *s++ );
putchar( '\n' );
}
}
//...
What you want, is the function strtok(3).
strtok uses a delimiter string to return parts of the string. By using " " as a delimiter, you can easily extract the names. For how to use the function read the man page I linked above. Or read this article.
You can print the names one at a time using the following code
#include <stdio.h>
#include <string.h>
int main
(int argc, char *argv[], char *envp[])
{
char a[] = "Bill Sarah Alice";
char *tok = strtok (a, " ");
while (tok) {
puts (tok);
tok = strtok (NULL, " ");
}
return 0;
}
so I wrote this simple program, to remove all Characters in a String Except Alphabets.
what I did was I made an array with ascii characters ( I know its not complete ), and then loop to check if the given array contains one of the ascii character in the ascii array if so then replace it with space, then we left with an array with just alphabet and spaces. then a for loop check the number of the alphabet character in the array and that would be the length of the new array (t starts with 1 so it could be place for the null terminator ) and last is the while loop where fill the new arrays with the alphabet characters and then puts() function to display it .
#include <stdio.h>
int main(void) {
int i=0,j=0,t=1;
char a[30];
char b[t];
char ascii[21] = {'0','1','2','3','4','5','6','7','8',
'9',' ', '!','#','#','$','%','^','&','*','(',')'};
printf("enter your line:");
fgets(a, 30, stdin);
for(i=0; a[i] != '\0'; i++)
{
for(j=0;ascii[j]!= '\0';j++)
{
if (a[i] == ascii [j] ) {
a[i] = ' ';
}
else continue;
}
}
for(i=0; a[i] != '\0'; i++)
{
if (a[i] != ' ') t++;
}
while (a[i] != '\0' & b[i] != '\0')
{
if (a[i] != ' ') {
a[i] = b[j];
j++;
}
i++;
}
puts(b);
}
the compiler shows this
enter your line:caris$mo89
�2j.�
i assume its garbage values and I don't really know where the problem exactly.
You can do that in less code
#include <stdio.h>
int main(void) {
char a[30];
int i = 0;
printf("enter your line:");
fgets(a, 30, stdin);
while(a[i] != '\0') {
//check if it's not an alphabet char uppercase and lowercase of course
if(!(a[i] >= 65 && a[i] <= 90 || a[i] >= 97 && a[i] <= 122)) {
a[i] = ' ';
}
i++;
}
printf("%s", a);
}
Trying to make a function that outputs the count of words a user enters into the program. I keep getting a value of 2 with this code and I am not sure why or where I am going wrong. If someone can point me in the right direction that would be great. Thanks!
Here is the code:
#include <stdio.h>
#include <string.h>
int wordcount(char string[101]){
int i, words = 0;
for(i=0;string[i] != '\0';i++)
{
if(string[i] != '\t' && string[i] != '\0'){
words++;
while(string[i] != ' ' && string[i] != '\t' && string[i] !=
'\0')
i++;
}
}
return words;
}
int main (void) {
char input[101];
printf("Word Counter\n");
printf("============\n");
printf("string to be analyzed: \n");
scanf("%100[^\n]", input);
wordcount(input);
printf(" %s - words = %i\n", input, wordcount(input));
}
The main problem now is there are two.
if(string[i] != '\t' && string[i] != '\0'){ deterioration, changing for the worse
i is +1 to twice in the for and while.
For example, it will change as follows.
int wordcount(char string[101]){
int i, words = 0;
for(i=0;string[i] != '\0'; i++){
if(string[i] != ' ' && string[i] != '\t'){// assuming not included the newline.
words++;
i += strcspn(&string[i], " \t") -1;// i point to last character of word
}
}
return words;
}
or i changes it will be in one place.
int wordcount(char string[]){
int i, words = 0;
char prev =' ';
for(i=0;string[i] != '\0'; i++){
if(isspace(prev) && !isspace(string[i])){//isspace in <ctype.h>
words++;//count front edge
}
prev = string[i];
}
return words;
}
I want to repace multiple spaces in a string by single space, however my following code doesn't work. What's the logical mistake?
#include<stdio.h>
#include<string.h>
main()
{
char input[100];
int i,j,n,z=0;
scanf("%d",&n);
z=n;
for(i=0;i<n;i++)
scanf("%c",&input[i]);
for(i=0;i<n;i++)
{
if(input[i]==' ' && (input[i+1]==' ' || input[i-1]==' '))
{
--z;
for(j=i;j<n;j++)
input[j]=input[j+1];
}
}
for(i=0;i<z;i++)
printf("%c",input[i]);
printf("\n");
}
I would do something like this:
void replace_multi_space_with_single_space(char *str)
{
char *dest = str; /* Destination to copy to */
/* While we're not at the end of the string, loop... */
while (*str != '\0')
{
/* Loop while the current character is a space, AND the next
* character is a space
*/
while (*str == ' ' && *(str + 1) == ' ')
str++; /* Just skip to next character */
/* Copy from the "source" string to the "destination" string,
* while advancing to the next character in both
*/
*dest++ = *str++;
}
/* Make sure the string is properly terminated */
*dest = '\0';
}
Of course, the above function requires you to properly terminate the string, which you currently do not.
What the function above does, is basically copy the string over itself. The exception is when there is a space, when multiple spaces are simply discarded.
Since the function modifies the source string, it can not be used on string literals.
The scanf is giving you some problem: it reads the \n you give after inputting the length n. So, you will miss the last character since for loop exits. The already given answers are good enough. But if you want to follow your own logic, try this:
void main()
{
char input[100];
int i = 0,j,n = 0;
while ((input[n] = getchar()) != '\n') {
n++;
}
input[n] = '\0';
while (i < n)
{
if(input[i]==' ' && (input[i+1]==' ' || input[i-1]==' '))
{
for(j=i;j<n;j++)
input[j]=input[j+1];
n--;
}
else
{
i++;
}
}
printf("%s\n",input);
printf("\n");
}
if(input[i]==' ' && (input[i+1]==' ' || input[i-1]==' '))
case " 1 3" : when i == 0 accses input[i-1] Out-of-Bounds
scanf("%d",&n);
remain newline, (input[0] <-- '\n')
fix to
scanf("%d%*c",&n);
#include <stdio.h>
char* uniq_spc(char* str){
char *from, *to;
int spc=0;
to=from=str;
while(1){
if(spc && *from == ' ' && to[-1] == ' ')
++from;
else {
spc = (*from==' ')? 1 : 0;
*to++ = *from++;
if(!to[-1])break;
}
}
return str;
}
int main(){
char input[]= " abc de f ";
printf("\"%s\"\n", uniq_spc(input));//output:" abc de f "
return 0;
}
Why make it more complicated than it needs to be? You can use strtok to check for single whitespaces and just ignore those. Then you can use strcat to concatenate the string into a full sentence and then you're done.
This is how I did it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char *pch;
char sentence[1000];
char without[1000];
printf("Sentence: ");
fgets(sentence,1000, stdin);
strtok(sentence, "\n"); // remove any newlines
pch = strtok(sentence, " ");
while(pch != NULL) {
strcat(without, pch);
strcat(without, " \0");
pch = strtok(NULL, " ");
}
without[strlen(without)-1] = '\0'; // remove extra whitespace at the end
printf("|%s|\n",without);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void remove_blanks(char* s);
int main()
{
char const s[] = {'1',' ',' ','2',' ',' ','3'};
remove_blanks(s);
printf("%s",s);
return 0;
}
void remove_blanks(char* s){
int i=0, delta=0, cnt=0;
for (i=0;s[i];++i){
if (s[i]==' ') cnt++;
if (cnt>1){
delta+=1;
cnt=0;
}
s[i-delta]=s[i];
if(delta>0) s[i]='\0';
}
}
You cant try this simple code:
#include <stdio.h>
#define IN 1
#define OUT 0
int main() {
int c, spaces, state;
spaces = 0;
state = OUT;
while ((c = getchar()) != EOF) {
if ( c == ' ') {
++spaces;
state = OUT;
}
else if (state == OUT) {
state = IN;
spaces = 0;
}
if (c == ' ' && spaces > 1 && state == OUT)
c = 0;
putchar(c);
}
return 0;
}
You have to fix the following for loop. the limit of your for loop should be z and not n
for(j=i;j<n;j++)
input[j]=input[j+1];
by
for(j=i;j<z;j++)
input[j]=input[j+1];
BTW: the fist charachter get by your scanf() (which read charachters) is newline (\n). this newline come from the first scanf() of decimal(%d)
#include<stdio.h>
#include<string.h>
int main(void)
{
char input[1000];
int i=0;
gets(input);
for(i=0;input[i]!='\0';i++)
{
if(input[i]!=' ' || input[i+1]!=' ')
printf("%c",input[i]);
}
return 0;
}