How to check if particular characters appeared in same order? - c

For example I have a string: PO-ELK=SAEER:SWE
- must always be before = and that should always be before :.
Is there a easy way I could check to see if those conditions are met in the string I input and if not an error is returned.

Just a little programming needed.
const char *symbol = "-=:";
const char *s = "PO-ELK=SAEER:SWE";
while (*s) {
if (*s == *symbol) symbol++;
s++;
}
if (*symbol) puts("Fail");
else puts("Success");

How about 3 calls to strchr()?
const char *s = "PO-ELK=SAEER:SWE";
const char *t;
if ((t = strchr(s, '-')) && (t = strchr(t, '=')) && (t = strchr(t, ':'))) puts("Success");
else puts("Failure");

Sort-of interesting problem, it might be good for code-golf
$ cat > yesno.c
#include <stdio.h>
#include <strings.h>
int main(int ac, char **av) {
char *s = "-=:",
*s0 = s,
*i = av[1];
while(*s && i && *i) {
if(index(s0, *i)) {
if(*i == *s) {
++i;
++s;
continue;
} else
break;
}
++i;
}
printf("%s\n", *s ? "no" : "yes");
}
^D
$ cc -Wall yesno.c
$ ./a.out PO-ELK=SAEER:SWE
There are some grey areas in the spec tho. Are the characters ever duplicated? And if so do we search for a subsequence that is in-order? Do we require that all three are found? Does the program need to be interactive or can it just use the shell args?

Use std::string::find. Make use of second argument.
First look for "-" and if it could be find, search for "=" passing position of "-" as start point. Then do the same for ":" with position of "=" as a second argument.

You can use the strchr function, which return a pointer to the character in the string. So you can call this function for each of the characters in question and check that the indexes are in the right order.
const char *str = "PO-ELK=SAEER:SWE";
const char *dashPtr = strchr(str,'-');
const char *equalPtr = strchr(str,'=');
const char *colonPtr = strchr(str,':');
if ((dashIdx == NULL) || (equalIdx == NULL) || (colonIdx == NULL)) {
printf("one of -, =, : not found\n");
} else {
if ((dashPtr < equalPtr) && (equalPtr < colonPtr)) {
printf("order correct\n");
} else {
printf("order incorrect\n");
}
}

Use state machine in this kind of problem :
Here is my solution, i didn't test it but it should give you some ideas
#include <string.h>
#include <stdio.h>
typedef enum {init, s1,s2,s3,end}eState;
int main()
{
char str[20] ="PO-ELK=SAEER:SWE";
int iExit = 0;
int i =0;
char c;
eState state = init;
while (!iExit)
{
c=str[i];
switch (state)
{
case init:
if (c =='-')
state = s1;
else if ((c =='=')||(c ==':'))
state = end;
break;
case s1:
if (c =='=')
state = s2;
else if(c ==':'||c=='-')
state = end;
break;
case s2:
if (c ==':')
state = s3;
else if(c =='='||c=='-')
state = end;
break;
case s3:
printf ("Succes \n");
iExit = 1;
break;
case end:
printf ("Error \n"),
iExit = 1;
break;
default :
break;
}
i++;
}
return 0;
}

You can use the idea shown in this demonstrative program. The advantage of this approach is that you can write just an if-statement to check a string.
#include <stdio.h>
#include <string.h>
int main( void )
{
const char *s = "PO-ELK=SAEER:SWE";
const char *t = "-=:";
size_t n = 0;
if ( s[n = strcspn( s + n, t )] == t[0] &&
s[n += 1 + strcspn( s + n + 1, t )] == t[1] &&
s[n += 1 + strcspn( s + n + 1, t )] == t[2] )
{
printf( "\"%s\" is a valid string\n", s );
}
else
{
printf( "\"%s\" is not a valid string\n", s );
}
s = "PO-ELK:SAEER=SWE";
n = 0;
if ( s[n = strcspn( s + n, t )] == t[0] &&
s[n += 1 + strcspn( s + n + 1, t )] == t[1] &&
s[n += 1 + strcspn( s + n + 1, t )] == t[2] )
{
printf( "\"%s\" is a valid string\n", s );
}
else
{
printf( "\"%s\" is not a valid string\n", s );
}
return 0;
}
The program output
"PO-ELK=SAEER:SWE" is a valid string
"PO-ELK:SAEER=SWE" is not a valid string
To guarantee that the string does not contain more than one of each target character you can write the condition the following way
if ( s[n = strcspn( s + n, t )] == t[0] &&
s[n += 1 + strcspn( s + n + 1, t )] == t[1] &&
s[n += 1 + strcspn( s + n + 1, t )] == t[2] &&
s[n += 1 + strcspn( s + n + 1, t )] == '\0' )

Related

Write a program that converts a string to an integer without using standard C library functions

#include <assert.h>
#include <stddef.h>
#include <string.h>
int StringToInteger(const char *str) {
int num = 0;
int sign = 1;
assert(str != NULL); //assert that str different from NULL
if (*str == '+' || *str == '-') {
sign = (*str == '-') ? -1 : 1;
str++;
return sign; // if sign start with character
}
while (*str != '\0') {
if (*str >= '0' && *str <= '9') {
num = num * 10 + (*str - '0');
} else {
return 0;
}
str++;
}
return 0;
}
I tried to write a different version of the code without using the regular conversion functions but with no success.
Problems:
Do not always return 0 #tkausl
No reason to return after finding a sign #Barmar
Delete that line and later in code adjust num per sign.
Tip: also run spell checker.
// return sign; // if sign start with charcter
// End of code
return num * sign; // Include this line
// return 0;
Advanced: avoid int overflow
Handle the INT_MIN text like StringToInteger("-2147483648")
Detect potential overflow before it happens. This prevents undefined behavior (UB).
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stddef.h>
int StringToInteger(const char* str) {
assert(str != NULL);
// TBD code if desired to ignore leading white-spaces.
int sign = *str;
if (*str == '+' || *str == '-') {
str++;
}
const char *first = s;
int num = 0;
while (*str >= '0' && *str <= '9') {
int digit = *str - '0';
if (num <= INT_MIN/10 && (num < INT_MIN/10 || digit > -(INT_MIN%10))) {
errno = ERANGE;
num = INT_MIN;
} else {
// Sum as a negative value as the - range is more than + range.
num = num * 10 - digit;
}
str++;
}
if (*str) {
; // May want to set errno.
return 0; // Non-null character stopped loop.
}
if (s == first) {
; // May want to set errno.
return 0; // No digits.
}
if (sign != '-') {
if (num < -INT_MAX) {
num = INT_MAX;
errno = ERANGE;
} else {
num = -num;
}
}
return num;
}
The function has many return statements that do not make sense as for example
return sign; // if sign start with charcter
And your function returns either sign or 0. In fact it does not take into account the sign of the stored value in the string.
Also take into account that the string can contain leading or trailing white space characters.
You could implement the function the same way.as standard C function strtol. A simplified function can ignore the case when the stored number is too big to fit in an object of the type int.
Here is a demonstration program that shows how the function can be implemented.
#include <ctype.h>
#include <stdio.h>
int StringToInteger( const char *str )
{
const int Base = 10;
int sign = 0;
while (isspace( ( unsigned char )*str )) ++str;
if (*str == '-' || *str == '+')
{
if (*str == '-') sign = 1;
++str;
}
int value = 0;
for (unsigned char c = *str; isdigit( c ); c = *++str )
{
int digit = c - '0';
value = Base * value + ( sign ? -digit : digit );
}
while (isspace( ( unsigned char )*str )) ++str;
return *str == '\0' ? value : 0;
}
int main( void )
{
const char *str = " -12345\t";
printf( "\"%s\" = %d\n", str, StringToInteger( str ) );
str = " 12345\t";
printf( "\"%s\" = %d\n", str, StringToInteger( str ) );
str = " 12345\tA";
printf( "\"%s\" = %d\n", str, StringToInteger( str ) );
str = " #12345\t";
printf( "\"%s\" = %d\n", str, StringToInteger( str ) );
str = " 123#45\t";
printf( "\"%s\" = %d\n", str, StringToInteger( str ) );
}
The program output is
" -12345 " = -12345
" 12345 " = 12345
" 12345 A" = 0
" #12345 " = 0
" 123#45 " = 0
Function converting string to integer (any base if you have enough digits/letters/symbols) to represent digits in this base.
int myisspace(int c)
{
switch(c)
{
case ' ':
case '\t':
case '\r':
case '\n':
return 1;
}
return 0;
}
char *mystrchr(const char *str, const char ch)
{
while(*str)
{
if(*str == ch) return str;
str++;
}
return NULL;
}
int long long cnv(const char *str, unsigned base)
{
const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
int sign = 1;
int long long result = 0;
if(str && (base >=2 && base < sizeof(digits)))
{
while(myisspace(*str)) str++;
if(*str == '-' || *str == '+') { sign = *str == '-' ? -1 : 1; str++;}
}
while(*str)
{
//you may check for overflow as well
//TODO integer overflow code if needed
char *rch = mystrchr(digits, *str);
if(!rch || (rch - digits) >= base)
{
if(!myisspace(*str))
{
result = 0;
break;
}
else
{
*str++;
continue;
}
}
result *= base;
result += rch - digits;
str++;
}
return result * sign;
}
int main(void)
{
printf("%lld\n", cnv("934", 10));
printf("%lld\n", cnv("934", 12));
printf("%lld\n", cnv("ffff", 16));
printf("%lld\n", cnv("01100110011", 2));
printf("%lld\n", cnv(" -01100110011", 2));
printf("%lld\n", cnv(" -42313442323", 5));
printf("%lld\n", cnv(" -42313442323 ", 12));
}

I need a program in C, which finds all the words that start and end with the same letter

I'm trying to make a program that counts all the words that start and end with the same character. in C
It tells me correctly which is the first and which is the last, I don't know how to make it show me the ones that are equal.
#include <stdio.h>
#include <string.h>
int main()
{
char s[50];
printf("Introdu propozitia : ");
gets(s);
int i, j = 0;
// Traversing the Character array
for (i = 0; i < strlen(s); i++) {
// To store first character of
// String if it is not a
// whitespace.
if (i == 0 && s[i] != ' ') {
printf("%c ", s[i]);
}
if (s[i] == ' ')
printf("%c", s[i -1]);
// To check whether Character
// is first character of
// word and if yes store it.
else if (i > 0 && s[i - 1] == ' ') {
printf(" %c ", s[i]);
}
else if (i>0 && s[i] == ' ')
printf("%c", s[i -1]);
if(s[i]==s[i-1])
Total ++;
printf("\n Sunt : %d", Total);
}
return 0;
}
For starters the function gets is unsafe and is not supported by the C Standard. Instead use either scanf or fgtes.
This if statement
if(s[i]==s[i-1])
Total ++;
does not make sense.
Using the function strlen in the for loop is inefficient and redundant.
To find starts and ends of words in a string you can use standard string functions strspn and strcspn.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
int main( void )
{
char s[50];
printf( "Introdu propozitia : " );
fgets( s, sizeof( s ), stdin );
size_t count = 0;
const char *delim = " \t\n";
for ( const char *p = s; *p; )
{
p += strspn( p, delim );
size_t n = strcspn( p, delim );
if (n != 0 && p[0] == p[n - 1])
{
++count;
}
p += n;
}
printf( "\nSunt : %zu\n", count );
}
Its output might look like
Introdu propozitia : 123454321 2345432 34543 454 5
Sunt : 5
If you want to output the words that satisfy the condition then add one statement in the if statement of the program
if (n != 0 && p[0] == p[n - 1])
{
++count;
printf( "%.*s\n", ( int )n, p );
}

How can i make first letter of all words in a string uppercase recursively? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I wonder how can i make this. I don't want any iteration or isalpha() and toupper() functions. We want to use our own code to read input. We assume that user enters all characters lowercase. This is what i've tried so far:
define MAX_LENGTH 100
int read_line(char str[],int);
void capitalize(char[]);
int main (void){
char A[MAX_LENGTH];
printf("Enter a text \n");
read_line(A, MAX_LENGTH);
capitalize(A);
puts(A);
}
int read_line(char str[],int n){
int ch,i=0;
while ((ch = getchar()) != '\n'){
if(i<MAX_LENGTH)
str[i++] = ch;
}
str[i] = '\0';
return i;
}
void capitalize(char str[]){
int x = strlen(str);
static int i = 0;
if(str[i]=='\0')
return;
if(str[i-1]==' '|| i == 0)
str[i] -= 32;
i++;
return capitalize(&str[i]);
}
Output is like this:
Enter a text:
asdf sdf df
Asdf sdf df
What is wrong with my code?
You code is invalid. For example even the function read_line
int read_line(char str[],int n){
int ch,i=0;
while ((ch = getchar()) != '\n'){
if(i<MAX_LENGTH)
str[i++] = ch;
}
str[i] = '\0';
return i;
}
is incorrect at least because when i is equal to MAX_LENGTH -1 there is an access memory beyond the character array
str[i] = '\0';
That is the condition of the loop is initially written incorrectly.
As for the recursive function then it can look for example the following way.
#include <stdio.h>
int is_blank( char c )
{
return c == ' ' || c == '\t';
}
char * capitalize( char *s )
{
if ( *s )
{
int blank = is_blank( *s );
if ( !blank )
{
*s &= ~' ';
}
capitalize( s + 1 );
if ( !blank && !is_blank( *( s + 1 ) ) && *( s + 1 ) )
{
*( s + 1 ) |= ' ';
}
}
return s;
}
int main(void)
{
char s[] = "hello everybody. how do you do?";
puts( s );
puts( capitalize( s ) );
return 0;
}
The program output is
hello everybody. how do you do?
Hello Everybody. How Do You Do?
Here is a similar demonstrative program but with your fixed function read_line.
#include <stdio.h>
#define MAX_LENGTH 100
int is_blank( char c )
{
return c == ' ' || c == '\t';
}
char * capitalize( char *s )
{
if ( *s )
{
int blank = is_blank( *s );
if ( !blank )
{
*s &= ~' ';
}
capitalize( s + 1 );
if ( !blank && !is_blank( *( s + 1 ) ) && *( s + 1 ) )
{
*( s + 1 ) |= ' ';
}
}
return s;
}
size_t read_line( char *s, size_t n )
{
int ch;
size_t i = 0;
while ( i + 1 < n && ( ch = getchar() ) != EOF && ch != '\n' )
{
s[i++] = ch;
}
s[i] = '\0';
return i;
}
int main(void)
{
char s[MAX_LENGTH];
read_line( s, MAX_LENGTH );
puts( s );
puts( capitalize( s ) );
return 0;
}
If to enter the string
hello everybody. how do you do?
then the program output will be the same as shown above.
hello everybody. how do you do?
Hello Everybody. How Do You Do?
If the bit-wise operations is unclear for you then you can substitute this statement
for this statement
*s &= ~' ';
for this statement
*s -= 'a' - 'A';
and this statement
*( s + 1 ) |= ' ';
for this statement
*( s + 1 ) += 'a' - 'A';
If to use your approach to the implementation of a recursive function with a static variable then it will be interesting to you why your function does not work will not be?
Let's consider it ignoring the first statement with the call of strlen.
void capitalize(char str[]){
int x = strlen(str);
static int i = 0;
if(str[i]=='\0')
return;
if(str[i-1]==' '|| i == 0)
str[i] -= 32;
i++;
return capitalize(&str[i]);
}
First of all after the first call the function for one string you may not call it a second time for another string because the static variable i will not be already equal to 0.
The condition of the if statement should be written at least like
if ( i == 0 || str[i-1]==' ' )
that is the order of sub-expressions shall be changed.
The return statement shall not contain an expression
return capitalize(&str[i]);
you could just write
capitalize(&str[i]);
Nevertheless the initial value of the pointer str was changed. However within the function you are using the index i relative the initial value of str of the first call of the function.
And I am sure it is interesting to you how correctly to rewrite the function, is not it?
The function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#define MAX_LENGTH 100
int is_blank( char c )
{
return c == ' ' || c == '\t';
}
char * capitalize( char *s )
{
static size_t i = 0;
if ( *( s + i ) )
{
if ( !is_blank( s[i] ) && ( i == 0 || is_blank( s[i-1] ) ) )
{
s[i] -= 'a' - 'A';
}
++i;
capitalize( s );
--i;
}
return s;
}
size_t read_line( char *s, size_t n )
{
int ch;
size_t i = 0;
while ( i + 1 < n && ( ch = getchar() ) != EOF && ch != '\n' )
{
s[i++] = ch;
}
s[i] = '\0';
return i;
}
int main(void)
{
char s[MAX_LENGTH];
read_line( s, MAX_LENGTH );
puts( s );
puts( capitalize( s ) );
return 0;
}
I would write the following:
void capitalize(char* str) {
if (! *str) return; // job done
*str = toupper(*str); // capitalize "correctly"
capitalize(++str);
}
the main problem is that you're using index and recursion at the same time, simple recursive solution would be:
void capitalize(char* str, bool start){
if (!*str) return; // end as soon as \0 is met
if (start)
if (*str >= 'a' && *str <= 'z') *str = (*str - 'a') + 'A'; // capitalize latin letters
capitalize(str + 1, *str == ' '); // work with next symbol
}
should be called as capitalize(str, true)
Should do the job:
void capitalize(char *s)
{
while(1) {
while (*s==' ') s++; // skip spaces
if (!*s) return; // check for end
if ('a'<=*s && *s<='z') *s -= 32; // capitalize if needed
while (*s && *s!=' ') s++; // advance
} // loop
}
(I call this "Stupid Character Processing")

C function for converting text to morse code

I'm trying to write a program where the morse code of the given text by the system is required. About the converting text to morse code, I wrote them all in main (separately from the program file itself). And now, my aim is to write it as a function in order to use it in the other functions of the program. Whenever I try, it gives a segmentation fault. Can anyone help me to construct the function itself from scratch?
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdint.h>
#include<ctype.h>
#include <time.h>
char * fileName1 = NULL;
char * fileName2 = NULL;
int main(int argc, char * argv[]) {
int n;
for (n = 0; n < argc; n++) {
// printf("Argument %s\n",argv[n]); // prints options delete this in the end,just for debugging
if (strcmp(argv[n], "-text") == 0) {
//text to morsecode
int c, v = 0;
char * str = (char * ) malloc(v);
str = (char * ) realloc(str, (c + strlen(argv[n + 1])));
strcat(str, argv[n + 1]);
strcat(str, " ");
char *alphamorse[]={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
char *nummorse[]={"-----",".----","..---","...--","....-",".....","-....","--...","---..","----."};
int i;
char str1[1000];
i = 0;
while (str[i] != '\0') {
if (str[i] != ' ' && (!isdigit(str[i]))) {
printf("%s ", alphamorse[toupper(str[i]) - 65]);
}
if (str[i] == ' ') {
printf(" ");
}
if (isdigit(str[i]) && str[i] != ' ') {
printf("%s ", nummorse[str[i] - 48]);
}
i++;
}
printf("\n");
// end of text to morsecode
}
if (strcmp(argv[n], "-o") == 0) {
//output = concat(output, argv[n + 1]);
n++;
continue;
}
if (strcmp(argv[n], "--") == 0) {
if (n + 1 <= argc) {
fileName1 = argv[++n];
printf(" fileName1=%s\n", fileName1);
}
if (n + 1 <= argc) {
fileName2 = argv[++n];
printf(" fileName2=%s\n", fileName2);
}
}
}
return 0;
}
You really don't need or want to be copying the parameters. It seems easiest to just do something like:
#include <stdio.h>
#include <ctype.h>
char *alphamorse[] = {
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", /* A - J */
"-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", /* K - T */
"..-", "...-", ".--", "-..-", "-.--", "--.." /* W - Z */
};
char *nummorse[]={
"-----", ".----", "..---", "...--", "....-",
".....", "-....", "--...", "---..", "----."
};
void
text_to_morse(char c, FILE *out)
{
if( islower(c) ) {
fputs(alphamorse[c - 'a'], out);
fputc(' ', out);
} else if( isdigit(c) ) {
fputs(nummorse[c - '0'], out);
fputc(' ', out);
} else if( isspace(c) ) {
fputc(c, out);
} else {
fputc(' ', out);
}
}
int
main(void)
{
int c;
while( ( c = tolower(getchar())) != EOF ) {
text_to_morse(c, stdout);
}
return 0;
}
Don't even bother with code for manipulating the output file. The shell exists for a reason, and there's no need to reimplement the wheel.
I don't know if this is the bug that's causing an issue, but it is a bug:
int c, v = 0;
char *str = (char *)malloc(v);
str = (char *)realloc(str, (c + strlen(argv[n+1])));
First, c is uninitialized. It could be any value, including a negative value. Hence, undefined behavior in your program.
Also, that malloc followed by a a realloc call isn't needed. Just allocate once and be done with it.
I think this is what you intended to do
size_t len = strlen(argv[n+1]);
str = (char*)malloc(len + 1 + 1); // +1 for space char to be appended, +1 again for null char
strcpy(str, argv[n+1]); // copy string
strcat(str, " "); // append a space
But there's an even simpler solution. You don't even need to copy argv[n+1] into str. Just declare str as a pointer and reference argv[n+1] directly.
const char* str = argv[n+1];
Now str and argv[n+1] reference the same string. And str is valid for the entirety of the program. The rest of your program remains the same.
This looks suspicious:
i = 0;
while (str[i] != '\0') {
if (str[i] != ' ' && (!isdigit(str[i]))) {
printf("%s ", alphamorse[toupper(str[i]) - 65]);
}
if (str[i] == ' ') {
printf(" ");
}
if (isdigit(str[i]) && str[i] != ' ') {
printf("%s ", nummorse[str[i] - 48]);
}
i++;
}
You are redundantly calling isdigit and evaluating to make sure str[i] is not a space. No point in checking if its a space if you already know it's a digit. Either it's a digit, a letter, or something that can't be converted. Your code will errneously treat puncutation marks as values to lookup in alphamorse. The following will skip over punctuation marks and just treat those characters as spaces.
i = 0;
while (str[i] != '\0') {
if ((str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= 'a' && str[i] <= 'z')) {
printf("%s ", alphamorse[toupper(str[i]) - 'A']);
}
else if (isdigit(str[i])) {
printf("%s ", nummorse[str[i] - '0']);
}
else {
printf(" ");
}
i++;
}
Everything after that, I don't know what it's for. General advice is that you parse the arguments from argv[] first. Then do the text conversion outside of the loop that iterates over the command line arguments. Then do your save to file code.

C - Counting words in a string

i've been trying to do a function that counts the number of words in a string in C. However, in some casas (as the one in the example) it should return 0 and not 1... any ideas of what could be wrong?
#import <stdio.h>
int contaPal(char s[]) {
int r;
int i;
r = 0;
for (i = 0; s[i] != '\0'; i++) {
if (s[i] == '\n')
r = r + 0;
if (s[i] != ' ' && s[i + 1] == ' ' && s[i + 1] != '\0')
r++;
if (s[i] != ' ' && s[i + 1] == '\0') {
r++;
}
}
return r;
}
int main () {
char s[15] = { ' ', '\n', '\0' };
printf("Words: %d \n", (contaPal(s)));
return 0;
}
You should not treat '\n' differently from any other whitespace character.
Here is a simpler version:
#include <ctype.h>
#include <stdio.h>
int contaPal(const char *s) {
int count = 0, hassep = 1;
while (*s) {
if (isspace((unsigned char)*s) {
hassep = 1;
} else {
count += hassep;
hassep = 0;
}
s++;
}
return count;
}
int main(void) {
char s[] = " \n";
printf("Words: %d\n", contaPal(s));
return 0;
}
I suppose that the word is any sequence of characters excluding white space characters.
Your function returns 1 because for the supplied string when the new line character is encountered the variable r is increased due to this condition
if (s[i] != ' ' && s[i + 1] == '\0') {
r++;
}
So the function implementation is wrong.
It can be defined the following way as it is shown in the demonstrative program
#include <stdio.h>
#include <ctype.h>
size_t contaPal( const char s[] )
{
size_t n = 0;
while ( *s )
{
while ( isspace( ( unsigned char )*s ) ) ++s;
n += *s != '\0';
while ( *s && !isspace( ( unsigned char )*s ) ) ++s;
}
return n;
}
int main(void)
{
char s[] = { ' ', '\n', '\0' };
printf( "Words: %zu\n", contaPal( s ) );
return 0;
}
Its output as you expect is
Words: 0
A simple illustration using existing character test functions:
int main(void)
{
int cnt = 0;
int numWords = 0;
BOOL trap = 0; //start count only after seeing a word
char *sentence = "This is a sentence, too long.";
//char *sentence2 = " ";//tested for empty string also
while (*sentence != '\0')
{
if ( isalnum (*sentence) ) //word is found, set trap and start count
{
sentence++; //alpha numeric character, keep going
trap = 1;
}
else if ( (( ispunct (*sentence) ) || ( isspace(*sentence) )) && trap)
{ //count is started only after first non delimiter character is found
numWords++;
sentence++;
while(( ispunct (*sentence) ) || ( isspace(*sentence) ))
{ //handle sequences of word delimiters
sentence++;
}
}
else //make sure pointer is increased either way
{
sentence++;
}
}
return 0;
}
The line:
if (s[i] != ' ' && s[i + 1] == ' ' && s[i + 1] != '\0')
r++;
Exactly matches the case when you look on '\n'.
You should use if ... else if ....

Resources