how to reverse order of words in string using C? - c

I am trying to reverse the order of words in a string, but my output is a bunch of junk that makes no sense. I don't know what is the problem, maybe the loops are broken.
Appreciate it if someone can explain what is wrong with my code below. I still new to C programming and this kind of problem is kind of frustrating.
#include<stdio.h>
int main()
{
//declare variable
char string[100], rev_string[100];
//declare number of loop
int i, j, len;
printf("enter the string: ");
scanf("%s",string);
//finding the length
len = strlen(string);
printf("strings length: %d\n", len);
for (i = len - 1; i >= 0; i--)
for (j = 0; j < len - 1; j++)
rev_string[j] = string[i];
rev_string[j] = '\0';
if (strcmp(string, rev_string) == 0)
printf("rev_string: %s is a palindrome", rev_string);
else
printf("rev_string : %s is not a palindrome words",rev_string);
return(0);
}

Your title is a bit confusing because your code seems to be a palindrome check and it should reverse the string, not the order of the words.
To reverse the string you can simply do:
for (i = 0; i < len; i++)
rev_string[i] = string[len - i - 1];

This code can help you :
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#define NCHARS 256 /* constant to count array size, covers ASCII + extended ASCII */
int ispalindrom (const char *s1, const char *s2)
{
int count[NCHARS] = {0}; /* counting array, covers all extended ASCII */
for (; *s1; s1++) /* loop over chars in string 1 */
if (!isspace(*s1)) /* if not whitespace */
count[(int)*s1]++; /* add 1 to index corresponding to char */
for (; *s2; s2++) /* loop over chars in string 2 */
if (!isspace(*s2)) /* if not whitespace */
count[(int)*s2]--; /* subtract 1 from index corresponding to char */
for (int i = 0; i < NCHARS; i++) /* loop over counting array */
if (count[i]) /* if any index non-zero, not anagram */
return 0;
return 1; /* all chars used same number of times -> anagram */
}
void main()
{
int i, j = 0, k = 0, x, len;
char str[100], str1[10][20], temp;
char str2[100];
printf("enter the string :");
scanf("%[^\n]s", str);
for (int i = 0;str[i] != '\0'; i++)
{
str2[i]=str[i];
}
/* reads into 2d character array */
for (int i = 0;str[i] != '\0'; i++)
{
if (str[i] == ' ')
{
str1[k][j]='\0';
k++;
j=0;
}
else
{
str1[k][j]=str[i];
j++;
}
}
str1[k][j] = '\0';
/* reverses each word of a given string */
for (int i = 0;i <= k;i++)
{
len = strlen(str1[i]);
for (int j = 0, x = len - 1;j < x;j++,x--)
{
temp = str1[i][j];
str1[i][j] = str1[i][x];
str1[i][x] = temp;
}
}
for (int i = 0;i <= k;i++)
{
printf("%s ", str1[i]);
}
printf("\n\n");
if (ispalindrom(str1, str2)==0)
{
printf("The word is Palindrom !\n");
}
else
{
printf("The word is not Palindrom !\n");
}
}

#include <stdbool.h>
#include <stdio.h>
bool ispalindrom(char *str,int k)
{
for(int i=0;i<k;i++)
{
if(str[i]!=str[k-i-1])
{
return false;
}
}
return true;
}
int main()
{
char string[100];
printf("enter the string: ");
scanf("%s",string);
if (ispalindrom(string,strlen(string)))
{
printf("\nrev_string: %s is a palindrome\n", string);
}
else
{
printf("\nrev_string : %s is not a palindrome words\n",string);
}
}

you can use a loop first to reverse the string first and then use strcomp()
#include<stdio.h>
#include <string.h>
int main()
{
//declare variable
char string[100], rev_string[100];
//declare number of loop
int i, j =0 , len;
printf("enter the string: ");
scanf("%s",string);
//finding the length
len = strlen(string);
printf("strings length: %d\n", len);
for (i = len - 1;i >= 0;i--){
rev_string[j] = string[i];
j++;
}
//check the rev_string if you want
/*for (i = 0; i < len; i++){
printf("%c\n",rev_string[i]);
}*/
if(strcmp(rev_string,string) == 0){
printf("Is Palindrome\n");
return(0);
}else{
printf("Is not Palindrome\n");
return(1);
}
}

Related

how do i remove the similar word in strings?

I have program to remove the similar words from string but this program only removing at once word not a repeating words.
For example input:
sabunkerasmaskera kera
and should an output:
sabunmas
This my code:
#include <stdio.h>
#include <string.h>
void remove(char x[100], char y[100][100], char words[100]) {
int i = 0, j = 0, k = 0;
for (i = 0; x[i] != '\0'; i++) {
if (x[i] == ' ') {
y[k][j] = '\0';
k++;
j = 0;
} else {
y[k][j] = x[i];
j++;
}
}
y[k][j] = '\0';
j = 0;
for (i = 0; i < k + 1; i++) {
if (strcmp(y[i], kata) == 0) {
y[i][j] = '\0';
}
}
j = 0;
for (i = 0; i < k + 1; i++) {
if (y[i][j] == '\0')
continue;
else
printf("%s ", y[i]);
}
printf ("\n");
}
int main() {
char x[100], y[100][100], kata[100];
printf ("Enter word:\n");
gets(x);
printf("Enter word to remove:\n");
gets(words);
remove(x, y, words);
return 0;
}
My program output its:
sabunkerasmaskerara
and that should not be the case. Maybe I need your opinion to fixed this program and also I need help to make it better.
Your solution does not work because it uses strcmp to compare the string portions, which only works if the substring is at the end of the string, as this makes it null-terminated.
You should instead use strstr to locate the matches and use memmove to shift the string contents.
There are other issues in your code:
do not use gets()
y is unnecessary for this task.
words is not defined
Here is a modified version:
#include <stdio.h>
#include <string.h>
char *remove_all(char *str, const char *word) {
size_t len = strlen(word);
if (len != 0) {
char *p = str;
while ((p = strstr(p, word)) != NULL) {
memmove(p, p + len, strlen(p + len) + 1);
}
}
return str;
}
int main() {
char str[100], word[100];
printf ("Enter string:\n");
if (!fgets(str, sizeof str, stdin))
return 1;
printf("Enter word to remove:\n");
if (!fgets(word, sizeof word, stdin))
return 1;
word[strcspn(word, "\n")] = '\0'; // strip the trailing newline if any
remove_all(str, word);
fputs(str, stdout);
return 0;
}

accepting case-insensitive input and printing them out correctly

Hi guys I wrote a better and improved hangman game that accepts lowercase input and uppercase input.
The only problem that I have is that for example if the String looks like this "tnt" it prints out every character big in the console. I am trying to make it print out the exact same string.
So if I input big 'T' then it should accept it and output small 't'.
Could someone help me?
Thank you in advance.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#define MAX_WORD 100
int get_word(char *word, int size) {
fgets(word, size, stdin);
int len = strlen(word);
if (len && word[len - 1] == '\n')
word[--len] = '\0';
for (int i = 0; i < len; ++i)
if (isalpha(word[i]))
word[i] = toupper(word[i]);
else
return -1;
return len;
}
void create_output(char *output, int len) {
for (int i = 0; i < len; ++i)
output[i] = '_';
output[len] = '\0';
}
void print_output(const char *output, const char *alpha, int tries) {
printf("(%d) ", tries);
for (int i = 0; output[i]; ++i)
printf("%c ", output[i]);
printf(" %s\n", alpha);
}
bool play_game(const char *word, int len) {
char alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char output[MAX_WORD];
create_output(output, len);
int tries = 0, guessed = 0;
while (tries < len && guessed < len) { // using word length for number of tries (?!)
print_output(output, alpha, tries);
printf("Guess: ");
char guess;
scanf(" %c", &guess);
guess = toupper(guess);
if (alpha[guess - 'A'] != ' ') {
for (int i = 0; i < len; ++i)
if (word[i] == guess && output[i] == '_') {
output[i] = word[i];
++guessed;
}
alpha[guess - 'A'] = ' ';
++tries;
}
}
print_output(output, alpha, tries);
return guessed == len;
}
int main() {
printf("Enter word to guess: ");
char word[MAX_WORD];
int len = get_word(word, sizeof word);
if (len == -1) {
printf("The word cannot contain spaces.\n");
return EXIT_FAILURE;
}
if (play_game(word, len))
printf("You win!\n");
else
printf("You lose.\nThe word was %s.\n", word);
return 0;
}

String array prints out trash values

So I have an assignment where I should delete a character if it has duplicates in a string. Right now it does that but also prints out trash values at the end. Im not sure why it does that, so any help would be nice.
Also im not sure how I should print out the length of the new string.
This is my main.c file:
#include <stdio.h>
#include <string.h>
#include "functions.h"
int main() {
char string[256];
int length;
printf("Enter char array size of string(counting with backslash 0): \n");
/*
Example: The word aabc will get a size of 5.
a = 0
a = 1
b = 2
c = 3
/0 = 4
Total 5 slots to allocate */
scanf("%d", &length);
printf("Enter string you wish to remove duplicates from: \n");
for (int i = 0; i < length; i++)
{
scanf("%c", &string[i]);
}
deleteDuplicates(string, length);
//String output after removing duplicates. Prints out trash values!
for (int i = 0; i < length; i++) {
printf("%c", string[i]);
}
//Length of new string. The length is also wrong!
printf("\tLength: %d\n", length);
printf("\n\n");
getchar();
return 0;
}
The output from the printf("%c", string[i]); prints out trash values at the end of the string which is not correct.
The deleteDuplicates function looks like this in the functions.c file:
void deleteDuplicates(char string[], int length)
{
for (int i = 0; i < length; i++)
{
for (int j = i + 1; j < length;)
{
if (string[j] == string[i])
{
for (int k = j; k < length; k++)
{
string[k] = string[k + 1];
}
length--;
}
else
{
j++;
}
}
}
}
There is a more efficent and secure way to do the exercise:
#include <stdio.h>
#include <string.h>
void deleteDuplicates(char string[], int *length)
{
int p = 1; //current
int f = 0; //flag found
for (int i = 1; i < *length; i++)
{
f = 0;
for (int j = 0; j < i; j++)
{
if (string[j] == string[i])
{
f = 1;
break;
}
}
if (!f)
string[p++] = string[i];
}
string[p] = '\0';
*length = p;
}
int main() {
char aux[100] = "asdñkzzcvjhasdkljjh";
int l = strlen(aux);
deleteDuplicates(aux, &l);
printf("result: %s -> %d", aux, l);
}
You can see the results here:
http://codepad.org/wECjIonL
Or even a more refined way can be found here:
http://codepad.org/BXksElIG
Functions in C are pass by value by default, not pass by reference. So your deleteDuplicates function is not modifying the length in your main function. If you modify your function to pass by reference, your length will be modified.
Here's an example using your code.
The function call would be:
deleteDuplicates(string, &length);
The function would be:
void deleteDuplicates(char string[], int *length)
{
for (int i = 0; i < *length; i++)
{
for (int j = i + 1; j < *length;)
{
if (string[j] == string[i])
{
for (int k = j; k < *length; k++)
{
string[k] = string[k + 1];
}
*length--;
}
else
{
j++;
}
}
}
}
You can achieve an O(n) solution by hashing the characters in an array.
However, the other answers posted will help you solve your current problem in your code. I decided to show you a more efficient way to do this.
You can create a hash array like this:
int hashing[256] = {0};
Which sets all the values to be 0 in the array. Then you can check if the slot has a 0, which means that the character has not been visited. Everytime 0 is found, add the character to the string, and mark that slot as 1. This guarantees that no duplicate characters can be added, as they are only added if a 0 is found.
This is a common algorithm that is used everywhere, and it will help make your code more efficient.
Also it is better to use fgets for reading input from user, instead of scanf().
Here is some modified code I wrote a while ago which shows this idea of hashing:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define NUMCHAR 256
char *remove_dups(char *string);
int main(void) {
char string[NUMCHAR], temp;
char *result;
size_t len, i;
int ch;
printf("Enter char array size of string(counting with backslash 0): \n");
if (scanf("%zu", &len) != 1) {
printf("invalid length entered\n");
exit(EXIT_FAILURE);
}
ch = getchar();
while (ch != '\n' && ch != EOF);
if (len >= NUMCHAR) {
printf("Length specified is longer than buffer size of %d\n", NUMCHAR);
exit(EXIT_FAILURE);
}
printf("Enter string you wish to remove duplicates from: \n");
for (i = 0; i < len; i++) {
if (scanf("%c", &temp) != 1) {
printf("invalid character entered\n");
exit(EXIT_FAILURE);
}
if (isspace(temp)) {
break;
}
string[i] = temp;
}
string[i] = '\0';
printf("Original string: %s Length: %zu\n", string, strlen(string));
result = remove_dups(string);
printf("Duplicates removed: %s Length: %zu\n", result, strlen(result));
return 0;
}
char *remove_dups(char *str) {
int hash[NUMCHAR] = {0};
size_t count = 0, i;
char temp;
for (i = 0; str[i]; i++) {
temp = str[i];
if (hash[(unsigned char)temp] == 0) {
hash[(unsigned char)temp] = 1;
str[count++] = str[i];
}
}
str[count] = '\0';
return str;
}
Example input:
Enter char array size of string(counting with backslash 0):
20
Enter string you wish to remove duplicates from:
hellotherefriend
Output:
Original string: hellotherefriend Length: 16
Duplicates removed: helotrfind Length: 10

Function that extracts words from text ( array of chars ) and put them in 2 dimensions array

I'm learning C and have some struggles.I have to make a program , which becomes a text (max 80 chars) and put the words from text in a char words[80][80] (every word must be only single time in this array! it is also defined as global) and count of times every word comes in the text in a int count[] (Index must be same as this from words[][]).
The function is called int extract_and_count(char *source,int *count).
I wrote some code ,but I'm not sure how exactly to implement this function.Can someone help me?
I'm also new to stackoverflow so if I have made any mistake, sorry.
Thats some of the code but its not to the end:
int extract_and_count(char *source,int *count){
char token[80][80];
char *p;
int i = 0;
p = strtok(source, " ");
while( p != NULL ){
strcpy(token[i],p);
printf("%s\n",*(token+i));
i++;
p = strtok(NULL , " ");
}
char word;
int value = 0, j;
for(i = 0 ; i < 80 ; i++){
word = token[i];
for(j = 0 ; j < 80 ; j++){
if(strcmp(word,token[i])==0){
value++;
}
}
}
return 1;
}
You need to check if a word has been found already. If so, just increment the global counter. Otherwise, copy the new word to the global array of strings.
Something like:
#include <stdio.h>
#include <string.h>
// Global variables to hold the results
char word[80][81];
int count[80] = { 0 };
int extract_and_count(char *source,int *strings_cnt){
char token[80][81];
char *p;
int i = 0;
// Find all words in the input string
p = strtok(source, " ");
while( p != NULL ){
strcpy(token[i],p);
// printf("%s\n",*(token+i));
i++;
p = strtok(NULL , " ");
}
// Find unique words and count the number a word is repeated
*strings_cnt = 0;
int j,k;
// Iterator over all words found in the input string
for(j = 0 ; j < i ; j++){
// Check if the word is already detected once
int found = 0;
for(k = 0 ; k < *strings_cnt ; k++){
if (strcmp(word[k], token[j]) == 0)
{
// The word already exists - increment count
found = 1;
count[k]++;
break;
}
}
if (!found)
{
// New word - copy it and set count to 1
strcpy(word[*strings_cnt], token[j]);
count[*strings_cnt] = 1;
(*strings_cnt)++;
}
}
return 1;
}
int main(void)
{
char s[] = "c language is difficult c is also fun";
int c, i;
printf("Searching: %s\n", s);
extract_and_count(s, &c);
printf("Found %d different words\n", c);
for (i=0; i<c; i++)
{
printf("%d times: %s\n", count[i], word[i]);
}
return 0;
}
Output:
Searching: c language is difficult c is also fun
Found 6 different words
2 times: c
1 times: language
2 times: is
1 times: difficult
1 times: also
1 times: fun
Above I tried to follow your codes style but I like to add these comments:
1) You don't really need the token array. The first loop can be changed so that it updates the final result directly.
2) Don't use global variable
3) The code can't handle normal separators like , . : and so on
4) You should put the word and the count into a struct.
Taken comment 1,2 and 4 in to consideration, the code could be:
#include <stdio.h>
#include <string.h>
// Global variables to hold the results
struct WordStat
{
char word[81];
int count;
};
int extract_and_count(char *source,int *strings_cnt, struct WordStat* ws, int max){
char *p;
int i = 0;
int k;
*strings_cnt = 0;
// Find all words in the input string
p = strtok(source, " ");
while( p != NULL ){
// Check if the word is already detected once
int found = 0;
for(k = 0 ; k < *strings_cnt ; k++){
if (strcmp(ws[k].word, p) == 0)
{
// The word already exists - increment count
found = 1;
ws[k].count++;
break;
}
}
if (!found)
{
// New word - copy it and set count to 1
strcpy(ws[*strings_cnt].word, p);
ws[*strings_cnt].count = 1;
(*strings_cnt)++;
}
i++;
p = strtok(NULL , " ");
}
return 1;
}
#define MAX_WORDS 80
int main(void)
{
struct WordStat ws[MAX_WORDS];
char s[] = "c language is difficult c is also fun";
int c, i;
printf("Searching: %s\n", s);
extract_and_count(s, &c, ws, MAX_WORDS);
printf("Found %d different words\n", c);
for (i=0; i<c; i++)
{
printf("%d times: %s\n", ws[i].count, ws[i].word);
}
return 0;
}
while( p != NULL ){
strcpy(token[i],p);
printf("%s\n",*(token+i));
i++;
p = strtok(NULL , " "); --> here you are just splitting the words
}
Now token will contain all the words in splitted manner, not as per your requirement of "each word only once". You can compare and copy the unique words to another array and in the same loop, you can count and update the count array.
Note: You should not use one counter variable on the whole, the array of counter only shall be used to count the words.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define NUM_OF_WORDS_MAX 80
#define MAX_WORD_LENGTH 79
#define S_(x) #x
#define S(x) S_(x) //number literal convert to string
char words[NUM_OF_WORDS_MAX][MAX_WORD_LENGTH+1];
int Words_entry = 0;
static inline int hash(const char *str){
return (tolower(*str) - 'a')*3;//3:(NUM_OF_WORDS_MAX / 26), 26 : a-z
}
char *extract(char **sp){//extract word
char *p = *sp;
while(*p && !isalpha(*p))//skip not alpha
++p;
if(!*p)
return NULL;
char *ret = p;//first word
while(*p && isalpha(*p))//skip alpha
++p;//*p = tolower(*p);
if(!*p){
*sp = p;
} else {
*p = '\0';
*sp = ++p;//rest
}
return ret;
}
int extract_and_count(char *source, int *count){
char *sp = source;
char *word;
int word_count = 0;
while(word = extract(&sp)){
if(Words_entry == NUM_OF_WORDS_MAX){
fprintf(stderr, "words table is full.\n");
return word_count;
}
int index = hash(word);
while(1){
if(*words[index]){
if(strcasecmp(words[index], word) == 0){//ignore case
++count[index];
break;
}
if(++index == NUM_OF_WORDS_MAX){
index = 0;
}
} else {
strcpy(words[index], word);
count[index] = 1;
++Words_entry;
break;
}
}
++word_count;
}
return word_count;
}
int main(void){
int count[NUM_OF_WORDS_MAX] = {0};
char text[MAX_WORD_LENGTH+1];
while(1==scanf("%" S(MAX_WORD_LENGTH) "[^\n]%*c", text)){//end if only enter press.
extract_and_count(text, count);
}
//print result
for(int i = 0; i < NUM_OF_WORDS_MAX; ++i){
if(*words[i]){
printf("%s : %d\n", words[i], count[i]);
}
}
return 0;
}

Anagram Solver, array[26] not working correctly

I've nearly finished my anagram solver program where I input two strings and get the result of whether they are anagrams of each other. For this example i'm using 'Payment received' and 'Every cent paid me'.
The problem i'm getting is when I output the letterCount arrays, letterCount1 is incorrect (it doesn't think there is a character 'd' but there is.) but letterCount2 is correct.
Can anyone see a problem with this because i'm completely baffled?
#include <stdio.h>
#include <string.h>
int checkAnagram(char string1[], char string2[])
{
int i;
int count = 0, count2 = 0;
int letterCount1[26] = {0};
int letterCount2[26] = {0};
for(i = 0; i < strlen(string1); i++)
{
if(!isspace(string1[i]))
{
string1[i] = tolower(string1[i]);
count++;
}
}
for(i = 0; i < strlen(string2); i++)
{
if(!isspace(string2[i]))
{
string2[i] = tolower(string2[i]);
count2++;
}
}
if(count == count2)
{
for(i = 0; i < count; i++)
{
if(string1[i] >='a' && string1[i] <= 'z')
{
letterCount1[string1[i] - 'a'] ++;
}
if(string2[i] >='a' && string2[i] <= 'z')
{
letterCount2[string2[i] - 'a'] ++;
}
}
printf("%s\n", string1);
for(i = 0; i < 26; i++)
{
printf("%d ", letterCount1[i]);
printf("%d ", letterCount2[i]);
}
}
}
main()
{
char string1[100];
char string2[100];
gets(string1);
gets(string2);
if(checkAnagram(string1, string2) == 1)
{
printf("%s", "Yes");
} else
{
printf("%s", "No");
}
}
That's because your count holds the count of non-space characters, but you keep the strings with the spaces.
For example, the string "hello world" has 11 characters, but if you run it through the loops your count will be 10 (you don't count the space). However, when you later go over the strings and count the appearance of each letter, you will go over the first 10 characters, therefore completely ignoring the last character - a 'd'.
To fix it, you need to go over all characters of the string, and only count the alphanumeric ones.
I fixed it for you:
#include <stdio.h>
#include <string.h>
int checkAnagram(char string1[], char string2[])
{
int i;
int count = 0, count2 = 0;
int letterCount1[26] = {0};
int letterCount2[26] = {0};
int len1 = strlen(string1);
int len2 = strlen(string2);
for(i = 0; i < len1; i++)
{
if(!isspace(string1[i]))
{
string1[i] = tolower(string1[i]);
count++;
}
}
for(i = 0; i < len2; i++)
{
if(!isspace(string2[i]))
{
string2[i] = tolower(string2[i]);
count2++;
}
}
if(count == count2)
{
for (i=0; i<len1; i++)
if (!isspace(string1[i]))
letterCount1[string1[i]-'a']++;
for (i=0; i<len2; i++)
if (!isspace(string2[i]))
letterCount2[string2[i]-'a']++;
int flag = 1;
for(i = 0; flag && i < 26; i++)
if (letterCount1[i] != letterCount2[i])
flag = 0;
return flag;
}
return 0;
}
main()
{
char string1[100];
char string2[100];
gets(string1);
gets(string2);
if(checkAnagram(string1, string2) == 1)
{
printf("%s", "Yes");
} else
{
printf("%s", "No");
}
}
First, don't calculate an string's length inside a loop. I extracted them into len1 and len2 variables.
Second, your loop was wrong! You shouldn't go up to count, you should go up to that string's length.
Third, you didn't return anything from checkAnagram function.

Resources