Program C count words (excluding numbers) [closed] - c

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 5 years ago.
Improve this question
I have come across a lot of counting words examples (like the one in the link below):
Counting words in a string - c programming
if(str[i]==' ')
{
i++;
}
and for digit is:
if(str[i]>='0' && str[i]<='9')
{
i++;
}
but what if the input were 'I have 12 apples.' and I only want the output to show "word count = 3"?

Assuming that you don't have words that contain alphanumeric combinations, like "foo12", then you could combine your code snippets, like this:
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[] = "Bex 67 rep";
int len = strlen(str);
int count = 0, i = 0;
while(str[i] != '\0')
{
if(str[i] == ' ')
{
if(i + 1 < len && ! (str[i + 1] >= '0' && str[i + 1] <= '9') && str[i + 1] != ' ')
count++;
}
i++;
}
printf("Word count = %d\n", count + 1); // Word count = 2
return 0;
}
where you loop over every character of the string, and when you find a whitespace, you check - if you are not at the last character of the string - if the next character is not a digit or a whitespace. If that's the case, then you can assume that the whitespace you encountered is precedended of a word, thus incease count.
Notice however that usually senteces do not start with a whitespace (which is an extra assumption for this answer), thus the number of words is one more than count.
In real life, use strtok() and check every token for its validity, since that's approach is just for demonstration and should be considered a bad approach.

#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="I have 12 apples";
char * pch;
unsigned long ul;
int cnt=0;
pch = strtok (str," ,.-");
while (pch != NULL)
{
ul = strtoul (pch, NULL, 0);
pch = strtok (NULL, " ,.-");
printf("%d\n", ul);
if(ul == 0)
cnt++;
}
printf("count is %d\n", cnt);
return 0;
}
String tokens parsed using strtok function.

My five cents.:)
#include <stdio.h>
#include <ctype.h>
size_t count_words( const char *s )
{
size_t n = 0;
const char *p = s;
while ( 1 )
{
int pos = 0;
sscanf( p, "%*[ \t]%n", &pos );
p += pos;
if ( sscanf( p, "%*s%n", &pos ) == EOF ) break;
if ( isalpha( ( unsigned char )*p ) ) ++n;
p += pos;
}
return n;
}
int main(void)
{
char s[] = "I have 12 apples";
printf( "The number of words is %zu\n", count_words( s ) );
return 0;
}
The program output is
The number of words is 3
And my advice is do not use the standard function strtok for such a task. First of all it may not deal with string literals. And it has a side effect of changing the original string.:)

Related

How to detect null values (and replace them) when reading from a file using sscanf [duplicate]

I am currently trying to parse UnicodeData.txt with this format: ftp://ftp.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.html However, I am hitting a problem in that when I try to read, say a line like the following.
something;123D;;LINE TABULATION;
I try to get the data from the fields by code such as the following. The problem is that fields[3] is not getting filled in, and scanf is returning 2. in is the current line.
char fields[4][256];
sscanf(in, "%[^;];%[^;];%[^;];%[^;];%[^;];",
fields[0], fields[1], fields[2], fields[3]);
I know this is the correct implementation of scanf(), but is there a way to get this to work, short of making my own scanf()?
scanf does not handle "empty" fields. So you will have to parse it on your own.
The following solution is:
fast, as it uses strchr rather than the quite slow sscanf
flexible, as it will detect an arbitrary number of fields, up to a given maximum.
The function parse extracts fields from the input str, separated by semi-colons. Four semi-colons give five fields, some or all of which can be blank. No provision is made for escaping the semi-colons.
#include <stdio.h>
#include <string.h>
static int parse(char *str, char *out[], int max_num) {
int num = 0;
out[num++] = str;
while (num < max_num && str && (str = strchr(str, ';'))) {
*str = 0; // nul-terminate previous field
out[num++] = ++str; // save start of next field
}
return num;
}
int main(void) {
char test[] = "something;123D;;LINE TABULATION;";
char *field[99];
int num = parse(test, field, 99);
int i;
for (i = 0; i < num; i++)
printf("[%s]", field[i]);
printf("\n");
return 0;
}
The output of this test program is:
[something][123D][][LINE TABULATION][]
Update: A slightly shorter version, which doesn't require an extra array to store the start of each substring, is:
#include <stdio.h>
#include <string.h>
static int replaceSemicolonsWithNuls(char *p) {
int num = 0;
while ((p = strchr(p, ';'))) {
*p++ = 0;
num++;
}
return num;
}
int main(void) {
char test[] = "something;123D;;LINE TABULATION;";
int num = replaceSemicolonsWithNuls(test);
int i;
char *p = test;
for (i = 0; i < num; i++, p += strlen(p) + 1)
printf("[%s]", p);
printf("\n");
return 0;
}
Just in case you would like to consider this following alternative, using scanfs and "%n" format-specifier, used for reading in how many characters have been read by far, into an integer:
#include <stdio.h>
#define N 4
int main( ){
char * str = "something;123D;;LINE TABULATION;";
char * wanderer = str;
char fields[N][256] = { 0 };
int n;
for ( int i = 0; i < N; i++ ) {
n = 0;
printf( "%d ", sscanf( wanderer, "%255[^;]%n", fields[i], &n ) );
wanderer += n + 1;
}
putchar( 10 );
for ( int i = 0; i < N; i++ )
printf( "%d: %s\n", i, fields[i] );
getchar( );
return 0;
}
On every cycle, it reads maximum of 255 characters into the corresponding fields[i], until it encounters a delimiter semicolon ;. After reading them, it reads in how many characters it had read, into the n, which had been zeroed (oh my...) beforehand.
It increases the pointer that points to the string by the amount of characters read, plus one for the delimiter semicolon.
printf for the return value of sscanf, and the printing of the result is just for demonstration purposes. You can see the code working on http://codepad.org/kae8smPF without the getchar(); and with for declaration moved outside for C90 compliance.
I don't think sscanf will do what you need: sscanf format %[^;] will match a non-empty sequence of not-semicolon characters. The alternative would be using readline with the separator being ';', like:
#include <iostream>
#include <sstream>
#include <string>
int main() {
using namespace std;
istringstream i { "something;123D;;LINE TABULATION;\nsomething;123D;;LINE TABULATION;\nsomething;123D;;LINE TABULATION;\n" };
string a, b, c, d, newline;
while( getline(i, a, ';') && getline(i, b, ';') && getline(i, c, ';') && getline (i, d, ';') && getline(i, newline) )
cout << d << ',' << c << '-' << b << ':' << a << endl;
}
(I have only seen you took the c++ tag off this question now, if your problem is c-only, I have another solution, below:)
#include <string.h>
#include <stdio.h>
int main() {
typedef char buffer[2048];
buffer line;
while( fgets(line, sizeof(line), stdin) > 0 ) {
printf("(%s)\n", line);
char *end = line;
char *s1 = *end == ';' ? (*end = '\0'), end++ : strtok_r(end, ";", &end);
char *s2 = *end == ';' ? (*end = '\0'), end++ : strtok_r(end, ";", &end);
char *s3 = *end == ';' ? (*end = '\0'), end++ : strtok_r(end, ";", &end);
char *s4 = *end == ';' ? (*end = '\0'), end++ : strtok_r(end, ";", &end);
printf("[%s][%s][%s][%s]\n", s4, s3, s2, s1);
}
}

Find the length of the longest word in a string. C language

Problem: I can't seem to get my test case 4 to work.
Question:
Write a C function that accepts an English sentence as a parameter, and returns the length of the longest word in the sentence. For example, if the sentence is "I am Tim.", then the length of the longest word "time" in sentence 3 will be returned.
Test Case 1:
Enter a string: I am lee.
longWordLength(): 3
Test Case 2:
Enter a string: There are two disciples in the class.
longWordLength(): 9
Test Case 3:
Enter a string: Good night!
longWordLength(): 5
Test Case 4:
Enter a string: Jovial
longWordLength(): 6
This is the code I have so far:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int longWordLength(char *s);
int main()
{
char str[80], *p;
printf("Enter a string: \n");
fgets(str, 80, stdin);
if (p=strchr(str,'\n')) *p = '\0';
printf("longWordLength(): %d\n", longWordLength(str));
return 0;
}
int longWordLength(char *s)
{
int i, count, max;
max = 0;
count = 0;
while( *(s) != '\0' )
{
if ( *(s) != '\0' && *(s) != ' ' && *(s) != '.' )
{
count++;
printf("current count is %d\n", count);
}
else
{
if(count>max)
{
max = count;
printf("There is a new max! It is %d\n", max);
count = 0;
}
count = 0;
printf("count is resetted!\n");
}
s++;
printf("reach the end of the while loop\n");
}
printf("current max outside while loop is: %d\n", max);
printf("exited\n");
return max;
}
Problem:
Your code does not work when the key word is at the end of a line.
That is because your max is updated inside that while loop and the while loop terminates when the null character is found. Since the null character is always appended to the end of your input string, the last word in a string does not contribute to the output. In this edge case, the loop does not give a chance to execute that else block in the final iteration.
In fact, your code will pass only Test Case 2 because all other cases contain the key word at the end of the input string.
Solution:
Even if you rectify that, your code may still fail if the sentence contains a punctuation mark other than the period.
For example: "Test Case!"
The new code will count "Case!" as a word of length 5 which is greater than the length of "Test" or "Case", and give a wrong answer.
You may look into some library functions that C has to offer in order to help you pass all edge cases.
If you need more assistance, I have made the required modifications to your code:
while( *(s) != '\0' )
{
// if ( *(s) != '\0' && *(s) != ' ' && *(s) != '.' )
// Why check the null character again?
// Spaces and period will not be the only punctuation marks
// You can check for all punctuation marks using ispunct() from <ctype.h>
if (!isspace(*s) && !ispunct(*s))
{
count++;
printf("current count is %d\n", count);
// You can update max here
if(count > max)
{
max = count;
printf("There is a new max! It is %d\n", max);
}
}
/*
Now you can eliminate this block of code
else
{
if(count>max)
{
max = count;
printf("There is a new max! It is %d\n", max);
count = 0;
}
count = 0;
printf("count is resetted!\n");
}
*/
// You can reset count after all that
else
{
count = 0;
printf("count is resetted!\n");
}
s++;
printf("reach the end of the while loop\n");
}
The code assumes that the input will be a proper English sentence.
P. S. This answer earned me the 1K reputation :)
For starters the function parameter should be declared with the qualifier const because within the function the passed string is not being changed. And the function return type should be size_t. It is the return type of the function strlen or the type of the value returned by the sizeof operator.
size_t longWordLength( const char *s);
The last word of a string does not take part in the calculation of the maximum word because the loop stops its iterations as soon as the next character is the terminating zero character '\0'.
It will be a bad idea to process the size of the last word outside the loop. All processing should be done within the loop.
Also your function does not take into account punctuation characters except the point.
For example for a sentence like this "How are you?" your function will give incorrect result.
Instead of checking each character whether it is for example a blank or not you could use standard C functions like strspn and strcspn.
Here is a demonstrative program that shows how the function can be implemented.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
size_t longWordLength( const char *s )
{
const char *delim = " \t";
size_t max = 0;
while ( *s )
{
s += strspn( s, delim );
if ( *s )
{
const char *first = s;
s += strcspn( s, delim );
const char *last = s;
while ( last != first && ispunct( ( unsigned char )*( last - 1 ) ) )
{
--last;
}
if ( max < last - first ) max = last - first;
}
}
return max;
}
int main(void)
{
const char *s = "Why are not you using string functions?!";
printf( "The size of the longest word is %zu\n", longWordLength( s ) );
return 0;
}
The program output is
The size of the longest word is 9
Another approach is to write two functions similar to strspn and strcspn that deal with blank and punctuation symbols.
Here is a demonstrative program.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
size_t count_non_alpha( const char *s )
{
size_t n = 0;
while ( isblank( ( unsigned char )s[n] ) || ispunct( ( unsigned char )s[n] ) )
{
++n;
}
return n;
}
size_t count_alpha( const char *s )
{
size_t n = 0;
while ( s[n] && !isblank( ( unsigned char )s[n] ) && !ispunct( ( unsigned char )s[n] ) )
{
++n;
}
return n;
}
size_t longWordLength( const char *s )
{
size_t max = 0;
while ( *s )
{
s += count_non_alpha( s );
if ( *s )
{
const char *first = s;
s += count_alpha( s );
if ( max < s - first ) max = s - first;
}
}
return max;
}
int main(void)
{
const char *s = "Why are not you using string functions?!";
printf( "The size of the longest word is %zu\n", longWordLength( s ) );
return 0;
}
The program output is the same as shown above.
Please refer to my comment to your original question.
You can resolve your problem by adding the following code, after your while loop.
if (*(s - 1) != ' ' && *(s - 1) != '.' )
{
if(count>max)
{
max = count;
printf("There is a new max! It is %d\n", max);
}
}
The code checks the last character in the input string. If it is not a word terminating character, then you didn't compare the last word with the current max in the loop and hence you do it after the loop completes.
use isalpha() to check the kind of character
don't forget to count the final word if it is followed by a '\0'
#include <stdio.h>
#include <ctype.h>
unsigned longest_word(char *str)
{
unsigned length,longest;
for(longest=length = 0; ; str++) {
if (isalpha(*str)) { length++; continue; }
if (length > longest) longest = length;
length = 0;
if (!*str) break;
}
return longest;
}
int main(void)
{
char * string1 = "The longest word is short";
char * string2 = "The longest word is unbelievable";
printf("%s: %u\n", string1, longest_word( string1) );
printf("%s: %u\n", string2, longest_word( string2) );
return 0;
}

Program to find the longest word in a string

I wrote a program to find the longest word in a string and print the number of letters in the longest word. But the code is not printing. I analyzed the program many times but I could not find the solution.
#include <stdio.h>
#include <string.h>
int main() {
char string[100] = "Hello Kurnool";
int i = 0, letters = 0, longest = 0;
start:
for (; string[i] !=' '; i++) {
letters++;
}
if (letters >= longest)
longest = letters;
if (string[i] == ' ') {
letters = 0;
i++;
goto start;
}
printf("%d", longest);
return 0;
}
Using goto is highly discouraged. You should convert your code to use a loop.
The main problem in your code is you do not stop the scan when you reach the end of the string.
Here is a modified version:
#include <stdio.h>
int main() {
char string[100] = "Hello Kurnool";
int i, letters, longest = 0, longest_pos = 0;
for (i = 0; string[i] != '\0'; i++) {
for (letters = 0; string[i] != '\0' && string[i] != ' '; i++) {
letters++;
}
if (letters > longest) {
longest = letters;
longest_pos = i - longest;
}
}
printf("longest word: %d letters, '%.*s'\n",
longest, longest, string + longest_pos);
return 0;
}
Note that the implementation can be simplified into a single loop:
#include <stdio.h>
int main() {
char string[100] = "Hello Kurnool";
int i, start = 0, longest = 0, longest_pos = 0;
for (i = 0; string[i] != '\0'; i++) {
if (string[i] == ' ') {
start = i + 1;
} else {
if (i - start > longest) {
longest = i - start;
longest_pos = start;
}
}
}
printf("longest word: %d letters, '%.*s'\n",
longest, longest, string + longest_pos);
return 0;
}
Below is my approach. You should use C's string manipulation functions. This is the correct way to deal with strings in C.
In the code below, first I acquire the required bytes to store the input string in heap. Then I use strtok to split the string into tokens based on a delemeter and get the length of each sub string. Finally I free the space that I have allocated with malloc.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define phrase "Hello Kurnool"
int main()
{
char* string = malloc(strlen(phrase)+1);
strcpy(string,phrase);
int longest=0;
char *token;
char delimeter[2] = " ";
/* get the first token */
token = strtok(string, delimeter);
/* walk through other tokens */
while( token != NULL ) {
printf( " %s\n", token );
if(longest < strlen(token)){
longest = strlen(token);
}
token = strtok(NULL, delimeter);
}
printf("%d",longest);
free(string);
return 0;
}
People say - dont use goto but there is nothing inherently wrong with goto. Only thing is if goto is not used judiciously, it makes code more difficult to understand and maintain. For example, the way you have used it in your program ( instead of goto, a loop is perfect fit in such cases). Check this:
To use goto or not?
What is wrong with using goto?
Coming to your code, the for loop condition does not have check for terminating null character
for (; string[i] !=' '; i++) {
Hence it will not stop at the end of string.
To find the number of letters in longest word of string, you can do:
#include <stdio.h>
#include <string.h>
int main() {
char string[100] = "Hello Kurnool";
int i, letters = 0, longest = 0;
for (i = 0; string[i] != '\0'; i++) {
if (string[i] != ' ') {
letters++;
if (letters > longest) {
longest = letters;
}
} else {
letters = 0;
}
}
printf("longest : %d\n", longest);
return 0;
}
First of all,Please avoid using Goto, it is not a good practice.
Secondly, your loop will run infinite times when it iterates the second time because:
for(;string[i]!=' ';i++) // Here String[i] will never be equal to ' ' As there is no white space after your last word.
You can never expect what might be going wrong with your program if you are using
goto statement
which is never advisable to use rather it's bad programming if you use it. Secondly it looks like you are stuck in an infinite loop so her is a solution to your problem:
#include<stdio.h>
#include<string.h>
void main()
{
char s[1000];
scanf("%s",s);
int i=0;
int letters;
int longest=0;
while(s[i]!=NULL)
{
if(s[i]==' ')
{
if(longest>=letters)
{longest=letters;}
letters=0;
}
else
{letters++;}
}
printf("%d\n",longest);
}
So, what I have done is assuming a string s which is the input given by the user. You itterate through s till the last input given by the user after which it encounters a NULL character. Now you are searching for the length of the longest word, so you create a variable letters for counting the no. of letters in each word of the string. And if the string s encounters a space indicating the end of a word, then you check if the variable longest is greater than or less than the word count. And again you initialize letters to 0, so that it can start counting the next word from 0 again.So, by this method at the end i.e. after the while loop terminates we get our required output which is stored in the variable longest.
So, I guess this will print the no. of letters in the longest word.

If loop in C not iterating properly

Writing a word counter on C. I'm counting the number of spaces in the string to determine the number of words. I'm guessing there's something wrong with my if statement. Sometimes it counts the number of words and other times it's throwing up random numbers? For instance "my red dog" has three words but "I drink rum" has one word and "this code makes no sense" has three. It's printing the length of the strings fine for each.
Here's the part of the code in question:
void WordCounter(char string[])
{ int counter = 1;
int i = 0;
int length = strlen(string);
printf("\nThe length of your string is %d", length);
for( i=0;i<length;i++){
if (string[i] == ' ')
{
counter+=1;
++i;
}
else
{
counter +=0;
++i;
}
}
printf("There are %d words in this sentence and i is equal to: %d", counter, i);
}
The i++ part of the for loop means that i is incremented at every loop, you should not do it again inside the loop. Also, your else is not necessary here. You'll want to remove bits to have:
for( i=0;i<length;i++) {
if (string[i] == ' ')
{
counter+=1;
}
}
The biggest problem with your posted code is that it incorrectly increments i where it should not.
for( i=0;i<length;i++){
if (string[i] == ' ')
{
counter+=1;
++i; // here
}
else
{
counter +=0;
++i; // here
}
}
Neither of the //here lines above are needed for what you appear to be trying to do. Furthermore, the entire else-block is pointless, as it modifies nothing except i, which it shouldn't be doing. Therefore, a more correct approach would be simply:
for(i=0; i<length; ++i)
{
if (string[i] == ' ')
++counter;
}
This increments counter whenever you index a space ' ' character. For a trivial algorithm, this will probably suffice to what you were trying.
Counting Spaces, Not Words
Your algorithm really doesn't count words, it simply counts the number of space characters encountered, plus one. This mean some inputs, such as those below (quotes used to note content in the string, not actually present), will not return an accurate word-count:
// shoud be zero, but returns one
""
// should be zero, but returns four (three spaces)
" "
// should be one, but returns five (two spaces, either side)
" word "
// should be two, but returns three (two spaces between)
"word word"
etc.
A more robust algorithm is required. Note this does NOT solve everything, but it makes great leaps in getting you closers to counting what we call "words". That is, non-whitespace characters separated by whitespace characters and potentially buttressing up to the end of the string.
This uses pointers rather than indexes. In my opinion it is simply easier to read, and declutters the code from indexing syntax, thereby amplifying what is really going on: consuming whitespace, then consuming non-whitespace that we call a "word". Comments inline should explain what is going on:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int WordCounter(const char *s)
{
int counter = 0;
// while we haven't reached terminating nullchar
while (*s)
{
// discard all whitespace until nullchar or non-whitespace found
for (; *s && isspace((unsigned char)*s); ++s);
// if not nullchar, we have the start of a "word"
if (*s)
{
++counter;
// discard all text until next whitespace or nullchar
for (; *s && !isspace((unsigned char)*s); ++s);
}
}
return counter;
}
int main()
{
const char *s1 = "There should be eight words in this string";
printf("\"%s\"\nwords: %d\n", s1, WordCounter(s1));
const char *s2 = " There should\t\t\tbe eight\n in\n this\n string too\n ";
printf("\"%s\"\nwords: %d\n", s2, WordCounter(s2));
const char *s3 = "One";
printf("\"%s\"\nwords: %d\n", s3, WordCounter(s3));
const char *s4 = "";
printf("\"%s\"\nwords: %d\n", s4, WordCounter(s4));
return 0;
}
Output
"There should be eight words in this string"
words: 8
" There should be eight
in
this
string too
"
words: 8
"One"
words: 1
""
words: 0
Not Perfect; Just Better
The prior algorithm still isn't perfect. To accurately extract single words would require knowledge of punctuation, potentially hyphenation, etc. But it is much, much closer to what appears to be the goal. Hopefully you get something out of it.
Your code has increment i in 3 different places. The increment needs only the loop.
Try this code:
for( i=0;i<length;i++){
if (string[i] == ' ')
{
counter++;
}
}
You´re incrementing i 2 times in the same loop. One in the for statement and one in the loop. It means you´re checking only one character on two. It can explain why all pair spaces are not in the count:
I put in Bolt all pair characters:
"my red dog": Both spaces are unpair numbers
"I drink rum": Both spaces are unpair numbers
Here is your corrected source code:
void WordCounter(char string[]){
int counter = 1;
int i = 0;
int length = strlen(string);
printf("\nThe length of your string is %d", length);
for( i=0;i<length;i++){
if (string[i] == ' ')
{
counter+=1;
}
}
printf("There are %d words in this sentence and i is equal to: %d", counter, i);
}
You even do not need the i variable
counter = 0;
while(*str)
counter += *str++ == ' ' ? 1 : 0;
printf("There are %d spaces (not words as you may have more spaces between words) in this sentence and length of the string is: %d", counter, length);
int isDelimeter(int ch, const char *delimiters)
{
return strchr(delimiters, ch) != NULL;
}
const char *skipDelimiters(const char *str, char *delimiters)
{
while (*str && isDelimeter(*str, delimiters)) str++;
return str;
}
const char *skipWord(const char *str, char *delimiters)
{
while (*str && !isDelimeter(*str, delimiters)) str++;
return str;
}
const char *getWord(const char *str, char *buff, char *delimiters)
{
while (*str && !isDelimeter(*str, delimiters)) *buff++ = *str++;
*buff = 0;
return str;
}
int countWords(const char *str, char *delimiters)
{
int count = 0;
while (*str)
{
str = skipDelimiters(str, delimiters);
if (*str) count++;
str = skipWord(str, delimiters);
}
return count;
}
int printWords(const char *str, char *delimiters)
{
char word[MAXWORDLENGTH];
int count = 0;
while (*str)
{
str = skipDelimiters(str, delimiters);
if (*str)
{
count++;
str = getWord(str, word, delimiters);
printf("%d%s word is %s\n", count, count == 1 ? "st" : count == 2 ? "nd" : count == 3 ? "rd" : "th", word);
}
}
return count;
}

Swap the 2nd character with the next-to-last

I have to change the 2nd letter with penultimate letter for word with more than 3 letters.
Example i have this string: Alex are mere
The result should be: Aelx are mree
But i get this when i run my program: Axel` aler
This is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i,n,j=0;
char text[81],cuv[44],l;
printf("Introduce-ti textul:");
gets(text);
for(i=0;i<strlen(text);i++)
{
if(text[i] != 32) {
cuv[j]=text[i];
j += 1;
} else {
n = strlen(cuv) - 1;
l= cuv[1];
cuv[1]=cuv[n-1];
cuv[n-1]=l;
printf("%s ",cuv);
strcpy(cuv,"");
j=0;
}
}
return 0;
}
First, you do not want to use gets. It was removed from the standard library because it was unsafe, use fgets instead. That being said, all you need to do is tokenize your input string into words, and then if the word is greater than 3 chars, swap the 2nd and next to last characters. One way would be:
#include <stdio.h>
#include <string.h>
#define MAXS 256
#define MAXW 64
int main (void) {
size_t len;
char str[MAXS] = {0};
char word[MAXW] = {0};
char *p = NULL;
fgets (str, MAXS, stdin); /* read input from stdin */
/* tokenize string */
for (p = strtok (str, " "); p; p = strtok (NULL, " \n"))
{
strncpy (word, p, MAXW - 1); /* copy token to word */
if ((len = strlen (word)) > 3) /* if word > 3 */
{
char tmp = word[1]; /* swap 2nd & next to last */
word[1] = word[len-2];
word[len-2] = tmp;
}
printf ("%s ", word);
}
putchar ('\n');
return 0;
}
Use/Output
$ printf "Alex are mere\n" | ./bin/swap2nd
Aelx are mree
or if you wanted to enter the text:
$ ./bin/swap2nd
Alex are mere
Aelx are mree
Second Method Using Start/End Pointers
You can also modify the original string ready be fgets in place by using nothing more than a start-pointer (p below) and end-pointer (ep below) to work your way down the string character-by-character, stopping each time the end-pointer points to a space, tab, or newline and then using the difference between the start and end pointers to check the length of the word and perform the character swap if the length is greater than 3 chars. You can work through each version and compare:
#include <stdio.h>
#define MAXS 256
int main (void) {
char str[MAXS] = {0};
char *p = NULL;
char *ep = NULL;
fgets (str, MAXS, stdin); /* read input from stdin */
p = ep = str;
while (*ep) /* for each char, if a space, tab or newline */
if (*ep == ' ' || *ep == '\t' || *ep == '\n') {
if ((ep - p) > 3) { /* if length > 3 */
char tmp = *(p + 1); /* swap chars */
*(p + 1) = *(ep - 2);
*(ep - 2) = tmp;
}
p = ++ep; /* set p to next word */
}
else
++ep;
printf ("%s\n", str);
return 0;
}
Use/Output
$ ./bin/swap2nd2
Alex are mere
Aelx are mree
Which approach you choose between these two methods, as well as the method posted by Vlad, is largely a matter of taste/choice. All are valid and are just different way of accomplishing the same thing. Let me know if you have questions.
Try the following approach
#include <stdio.h>
int main( void )
{
char s[] = "Alex Chiurtu";
char t[sizeof( s )];
size_t i = 0, j = 0;
do
{
t[i] = s[i];
if ( s[i] != ' ' && s[i] != '\t' && s[i] != '\0' )
{
++j;
}
else if ( j != 0 )
{
if ( j > 3 )
{
char c = t[i-j + 1];
t[i-j+1] = t[i-2];
t[i-2] = c;
}
j = 0;
}
} while ( s[i++] );
puts( s );
puts( t );
return 0;
}
The program output is
Alex Chiurtu
Aelx Ctiurhu
Take into account that function gets is unsafe and is not supported by the C Standard any more.
Also it is a bad idea to use magic numbers like 32. Its meaning is unclear.
In your program array cuv was not zero initialized therefore the following statement
n = strlen(cuv) - 1;
results in undefined behaviour of the program. Also it is not a good idea each time to calculate the length of the string.

Resources