Reading In txt File and Extracting Elements from Input Problem - c

I have been attempting to fix this for hours. I am trying to read a file called wiktionary called "stuff.txt" which has input of the form:
10000
5627187200 the
3395006400 of
2994418400 and
2595609600 to
1742063600 in
...
The 10000 represents the number of lines. I am then reading it in using a function read_in_terms, and extracting the number (weight) and the word (word) from it. I have tested my get_word and get_weight functions seperately and they seem to be working. However, when I am reading in, my get_word function is not returning the word .... the get_weight number is...
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* concat(const char *s1, const char *s2) {
char *result = malloc(strlen(s1) + strlen(s2) + 1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
// from a string of the form " 29480398934 the" it returns number
long get_weight(char *string) {
long length = strlen(string);
char number[200];
int count = 0;
// Here I am cycling through until X__X combination
// I only add to the number if it is not " "
for (int i = 0; i < length; i++) {
if (string[i-1] != ' ' && string[i] == ' ' && string[i+1] == ' ' && string[i+1] != ' ') {
break;
} else if (string[i] != ' '){
number[count] = string[i];
count++;
}
}
number[count] = '\0';
return atol(number); // converts it to a long and then returns
}
// from a string of the form " 453495834 word" it returns word
char * get_word(char* string) {
long length = strlen(string);
char word[200];
int count = 0;
// the double space detection only works once we reach a character
// this becomes 1 once that happens, allowing us to proceed to the next part
int blocker = 0;
for (int i = 0; i < length; i++) {
if (string[i] != ' '){
blocker++;
}else if (blocker > 0 && string[i] == ' ' && string[i+1] == ' ') {
int int_count = i+1;
while (string[int_count] != '\0') {
int_count++;
word[count] = string[int_count];
count++;
}
}
}
word[count] = '\0';
// now I need to copy this string into malloc
char *str = (char *)malloc(count*sizeof(char));
strcpy(str, word);
return str;
}
void read_in_terms(int *pnterms, char *filename) {
char part1[] = "/Users/adammartinez/Desktop/";
char* title = concat(part1,filename);
FILE *fp = fopen(title, "r");
char line[200];
fgets(line, sizeof(line), fp);
int num_lines = atoi(line);
for (int i = 0; i < num_lines; i++){
fgets(line, sizeof(line), fp);
printf("%ld \n", get_weight(line));
printf("%s \n", get_word(line)); // NOT RETURNING WORDS
}
}
int main(void) {
//char* test_str = " 547584758475 the";
//printf("%s %ld", get_word(test_str), get_weight(test_str));
int terms = 1000;
int *pointer = &terms;
read_in_terms(pointer, "stuff.txt");
return 0;
}

It seems to work fine on my computer. Please look at the output below and tell me if it's what you're looking for. I set part1 to "" and I changed the number of lines in stuff.txt to 5.
5627187200
the
3395006400
of
2994418400
and
2595609600
to
1742063600
in

Related

Functions works only 1 time

I've encountered a problem with my code where the function I made rotate_left that's supposed to take the first word in a given string and puts it at the end of that string and that function works but when it tried to activate it twice it doesn't do anything other than printing the same result the first function printed anyone got any ideas about it?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define MAX 80
void rotate_left(char str[])
{
int j = 0;
int i = 0;
char Temp[MAX];
char Temp2[MAX];
while (str[i] != ' ')
{
i++;
}
Temp[i] = '\0';
strncpy(Temp, str, i);
strcat(str, " ");
while (str[i] != '\0')
{
Temp2[j] = str[i];
i++;
j++;
}
Temp2[j] = '\0';
strcat(Temp2, Temp);
printf("%s\n", Temp2);
}
int main()
{
char str[MAX];
char Temp2[MAX];
printf("Enter Your String To Swtich The : ");
gets(str);
rotate_left(str);
rotate_left(str);
rotate_left(str);
return 0;
}
You have two bugs in these codes :
First you must copy the rotated string in the passed one, printing the result is not sufficient. Next you must remove the space at the beginning of the extracted word otherwise the new string start with a space.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define MAX 80
void rotate_left(char str[])
{
int j = 0;
int i = 0;
char Temp[MAX];
char Temp2[MAX];
// If the first space is not removed (see below), the next time
// the function is called, this loop stops immediately. It's why
// the second rotation didn't occur
while (str[i] != ' ')
{
i++;
}
Temp[i] = '\0';
strncpy(Temp, str, i);
strcat(str, " ");
i++; //<====== removes the space
while (str[i] != '\0')
{
Temp2[j] = str[i];
i++;
j++;
}
Temp2[j] = '\0';
strcat(Temp2, Temp);
strncpy(str, Temp2, strlen(Temp2) + 1); //<====== copies the string
printf("%s\n", str);
}
int main()
{
char str[MAX] = "Enter Your String To Switch The";
char Temp2[MAX];
for (int i=0; i<7; i++) rotate_left(str);
return 0;
}
Output :
Your String To Switch The Enter
String To Switch The Enter Your
To Switch The Enter Your String
Switch The Enter Your String To
The Enter Your String To Switch
Enter Your String To Switch The
Your String To Switch The Enter
I didn't handle special cases (if there is no space in the provided string for instance) and I removed the interactive dimension (gets) for the example.
Your code has issues:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define MAX 80
void rotate_left(char str[])
{
int j = 0;
int i = 0;
char Temp[MAX];
char Temp2[MAX];
while (str[i] != ' ')
{
i++;
}
in the code below you are having a security leak and a potential problem because you have temp variables in the stack and you are touching these without boundary checks: Example of a buffer overflow leading to a security leak
you need to write code with boundary checks especially when the variable is in the stack:
while (i < MAX /*or i < sizeof(str)*/ && str[i] != ' ' && str[i] != '\0' /*Null check also?*/ )
{
i++;
}
If you call this method with a string without space in it then god knows what will it result,
There are other issues as well like "strncpy(str, Temp2, strlen(Temp2) + 1);" this is not how this method is intended to be called as it should be "strncpy(str, Temp2, sizeof(str));": https://linux.die.net/man/3/strncpy
Let me write you sample code it will be faster for you to track some of the missing checks:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 80
/* just your code with safety checks so you can track why it fails */
int rotate_left(char str[], const size_t inputSize)
{
int j = 0;
int i = 0;
char Temp[MAX];
char Temp2[MAX];
while (i < inputSize && str[i] != ' ' && str[i] != '\0')
{
i++;
}
if (i == inputSize || str[i] == '\0')
{
// string without any space in it so no need to rotate?
return 0;
}
if (i + 1/*+1 to include null*/ >= MAX) {
// We dont have enough memory to handle this request
return -1;
}
strncpy(Temp, str, i);
Temp[i] = '\0';
++i;
while (i < inputSize && j < MAX && str[i] != '\0')
{
Temp2[j] = str[i];
i++;
j++;
}
if (i == inputSize) {
// String is not null terminated?
return -1;
}
if (j + 2 /*Include space and null character*/ >= MAX) {
// We dont have enough memory to handle this request
return -1;
}
Temp2[j] = ' ';
Temp2[j + 1] = '\0';
strncat(Temp2, Temp, sizeof(Temp2));
strncpy(str, Temp2, inputSize); //<====== copies the string
printf("%s\n", str);
return 0;
}
/* bit more optimization */
errno_t rotate_left_optimized(char str[], const size_t inputSize)
{
errno_t lastCall;
char temp[MAX];
int i = 0;
while (i < inputSize && str[i] != ' ' && str[i] != '\0')
{
i++;
}
if (i == inputSize || str[i] == '\0')
{
// string without any space in it so no need to rotate?
return 0;
}
const size_t inputLen = strnlen(str, inputSize);
if (i + 1 /* Include lazy space character */>= sizeof(temp)) {
// We dont have enough memory to handle this request
return -1;
}
// hidden assert(str[i] == ' ');
temp[0] = ' ';
memcpy(temp + 1, str, i);
memmove(str, str + i + 1, inputLen);
lastCall = strncat_s(str, inputSize, temp, i + 1);
if (!lastCall)
{
return lastCall;
}
return 0;
}
int main()
{
char str[MAX] = "Enter Your String To Switch The";
for (int i = 0; i < 7; i++) {
if (rotate_left_optimized(str, MAX)) {
perror("failed to rotate");
exit(EXIT_FAILURE);
}
printf("%s\n", str);
}
return 0;
}

Count the number of words using C [duplicate]

I need to write a function that will count words in a string. For the
purpose of this assignment, a "word" is defined to be a sequence
of non-null, non-whitespace characters, separated from other words by
whitespace.
This is what I have so far:
int words(const char sentence[ ]);
int i, length=0, count=0, last=0;
length= strlen(sentence);
for (i=0, i<length, i++)
if (sentence[i] != ' ')
if (last=0)
count++;
else
last=1;
else
last=0;
return count;
I am not sure if it works or not because I can't test it until my whole program is finished and I am not sure it will work, is there a better way of writing this function?
You needed
int words(const char sentence[])
{
}
(note braces).
For loops go with ; instead of ,.
Without any disclaimer, here's what I'd have written:
See it live http://ideone.com/uNgPL
#include <string.h>
#include <stdio.h>
int words(const char sentence[ ])
{
int counted = 0; // result
// state:
const char* it = sentence;
int inword = 0;
do switch(*it) {
case '\0':
case ' ': case '\t': case '\n': case '\r': // TODO others?
if (inword) { inword = 0; counted++; }
break;
default: inword = 1;
} while(*it++);
return counted;
}
int main(int argc, const char *argv[])
{
printf("%d\n", words(""));
printf("%d\n", words("\t"));
printf("%d\n", words(" a castle "));
printf("%d\n", words("my world is a castle"));
}
See the following example, you can follow the approach : count the whitespace between words .
int words(const char *sentence)
{
int count=0,i,len;
char lastC;
len=strlen(sentence);
if(len > 0)
{
lastC = sentence[0];
}
for(i=0; i<=len; i++)
{
if((sentence[i]==' ' || sentence[i]=='\0') && lastC != ' ')
{
count++;
}
lastC = sentence[i];
}
return count;
}
To test :
int main()
{
char str[30] = "a posse ad esse";
printf("Words = %i\n", words(str));
}
Output :
Words = 4
#include <ctype.h> // isspace()
int
nwords(const char *s) {
if (!s) return -1;
int n = 0;
int inword = 0;
for ( ; *s; ++s) {
if (!isspace(*s)) {
if (inword == 0) { // begin word
inword = 1;
++n;
}
}
else if (inword) { // end word
inword = 0;
}
}
return n;
}
bool isWhiteSpace( char c )
{
if( c == ' ' || c == '\t' || c == '\n' )
return true;
return false;
}
int wordCount( char *string )
{
char *s = string;
bool inWord = false;
int i = 0;
while( *s )
{
if( isWhiteSpace(*s))
{
inWord = false;
while( isWhiteSpace(*s) )
s++;
}
else
{
if( !inWord )
{
inWord = true;
i++;
}
s++;
}
}
return i;
}
Here is one of the solutions. It counts words with multiple spaces or just space or space followed by the word.
#include <stdio.h>
int main()
{
char str[80];
int i, w = 0;
printf("Enter a string: ");
scanf("%[^\n]",str);
for (i = 0; str[i] != '\0'; i++)
{
if((str[i]!=' ' && str[i+1]==' ')||(str[i+1]=='\0' && str[i]!=' '))
{
w++;
}
}
printf("The number of words = %d", w );
return 0;
}
I know this is an old thread, but perhaps someone needs a simple solution, just checks for blank space in ascii and compares current char to that while also makign sure first char is not a space, cheers!
int count_words(string text){
int counter = 1;
int len = strlen(text);
for(int i = 0; i < len; i++){
if(text[i] == 32 && i != 0) {
counter++;
}
}
return counter;}
Here is another solution:
#include <string.h>
int words(const char *s)
{
const char *sep = " \t\n\r\v\f";
int word = 0;
size_t len;
s += strspn(s, sep);
while ((len = strcspn(s, sep)) > 0) {
++word;
s += len;
s += strspn(s, sep);
}
return word;
}
#include<stdio.h>
int main()
{
char str[50];
int i, count=1;
printf("Enter a string:\n");
gets(str);
for (i=0; str[i]!='\0'; i++)
{
if(str[i]==' ')
{
count++;
}
}
printf("%i\n",count);
}
#include<stdio.h>
#include<string.h>
int getN(char *);
int main(){
char str[999];
printf("Enter Sentence: "); gets(str);
printf("there are %d words", getN(str));
}
int getN(char *str){
int i = 0, len, count= 0;
len = strlen(str);
if(str[i] >= 'A' && str[i] <= 'z')
count ++;
for (i = 1; i<len; i++)
if((str[i]==' ' || str[i]=='\t' || str[i]=='\n')&& str[i+1] >= 'A' && str[i+1] <= 'z')
count++;
return count;
}
#include <stdio.h>
int wordcount (char *string){
int n = 0;
char *p = string ;
int flag = 0 ;
while(isspace(*p)) p++;
while(*p){
if(!isspace(*p)){
if(flag == 0){
flag = 1 ;
n++;
}
}
else flag = 0;
p++;
}
return n ;
}
int main(int argc, char **argv){
printf("%d\n" , wordcount(" hello world\nNo matter how many newline and spaces"));
return 1 ;
}
I found the posted question after finishing my function for a C class I'm taking. I saw some good ideas from code people have posted above. Here's what I had come up with for an answer. It certainly is not as concise as other's, but it does work. Maybe this will help someone in the future.
My function receives an array of chars in. I then set a pointer to the array to speed up the function if it was scaled up. Next I found the length of the string to loop over. I then use the length of the string as the max for the 'for' loop.
I then check the pointer which is looking at array[0] to see if it is a valid character or punctuation. If pointer is valid then increment to next array index. The word counter is incremented when the first two tests fail. The function then will increment over any number of spaces until the next valid char is found.
The function ends when null '\0' or a new line '\n' character is found. Function will increment count one last time right before it exit to account for the word preceding null or newline. Function returns count to the calling function.
#include <ctype.h>
char wordCount(char array[]) {
char *pointer; //Declare pointer type char
pointer = &array[0]; //Pointer to array
int count; //Holder for word count
count = 0; //Initialize to 0.
long len; //Holder for length of passed sentence
len = strlen(array); //Set len to length of string
for (int i = 0; i < len; i++){
//Is char punctuation?
if (ispunct(*(pointer)) == 1) {
pointer += 1;
continue;
}
//Is the char a valid character?
if (isalpha(*(pointer)) == 1) {
pointer += 1;
continue;
}
//Not a valid char. Increment counter.
count++;
//Look out for those empty spaces. Don't count previous
//word until hitting the end of the spaces.
if (*(pointer) == ' ') {
do {
pointer += 1;
} while (*(pointer) == ' ');
}
//Important, check for end of the string
//or newline characters.
if (*pointer == '\0' || *pointer == '\n') {
count++;
return(count);
}
}
//Redundent return statement.
count++;
return(count);
}
I had this as an assignment...so i know this works.
The function gives you the number of words, average word length, number of lines and number of characters.
To count words, you have to use isspace() to check for whitespaces. if isspace is 0 you know you're not reading whitespace. wordCounter is a just a way to keep track of consecutive letters. Once you get to a whitespace, you reset that counter and increment wordCount. My code below:
Use isspace(c) to
#include <stdio.h>
#include <ctype.h>
int main() {
int lineCount = 0;
double wordCount = 0;
double avgWordLength = 0;
int numLines = 0;
int wordCounter = 0;
double nonSpaceChars = 0;
int numChars = 0;
printf("Please enter text. Use an empty line to stop.\n");
while (1) {
int ic = getchar();
if (ic < 0) //EOF encountered
break;
char c = (char) ic;
if (isspace(c) == 0 ){
wordCounter++;
nonSpaceChars++;
}
if (isspace(c) && wordCounter > 0){
wordCount++;
wordCounter =0;
}
if (c == '\n' && lineCount == 0) //Empty line
{
break;
}
numChars ++;
if (c == '\n') {
numLines ++;
lineCount = 0;
}
else{
lineCount ++;
}
}
avgWordLength = nonSpaceChars/wordCount;
printf("%f\n", nonSpaceChars);
printf("Your text has %d characters and %d lines.\nYour text has %f words, with an average length of %3.2f ", numChars, numLines, wordCount, avgWordLength);
}
Here is one solution. This one will count words correctly even if there are multiple spaces between words, no spaces around interpuncion symbols, etc. For example: I am,My mother is. Elephants ,fly away.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int countWords(char*);
int main() {
char string[1000];
int wordsNum;
printf("Unesi nisku: ");
gets(string); /*dont use this function lightly*/
wordsNum = countWords(string);
printf("Broj reci: %d\n", wordsNum);
return EXIT_SUCCESS;
}
int countWords(char string[]) {
int inWord = 0,
n,
i,
nOfWords = 0;
n = strlen(string);
for (i = 0; i <= n; i++) {
if (isalnum(string[i]))
inWord = 1;
else
if (inWord) {
inWord = 0;
nOfWords++;
}
}
return nOfWords;
}
this is a simpler function to calculate the number of words
int counter_words(char* a){`
// go through chars in a
// if ' ' new word
int words=1;
int i;
for(i=0;i<strlen(a);++i)
{
if(a[i]==' ' && a[i+1] !=0)
{
++words;
}
}
return words;}

Splitting a string to an array of strings

I'm trying to split a sentence the user inputs to an array of words so I can later manipulate the words separately as strings.
The code is compiling but prints only garbage after the user input.
I tried debugging but don't see the problem. Can someone help me fix it?
#include <stdio.h>
#include <string.h>
int main() {
char str[1000];
int i = 0;
char rev[1000][1000];
int r = 0;
puts("Enter text:");
gets(str);
int k, length = 0;
printf_s("So the words are:\n");
while (str[i] != '\0') {
if (str[i] == ' ') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != ' ');
printf(" ");
length = (-1);
r++;
} else
if (str[i + 1] == '\0') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != '\0');
length = 0;
r++;
}
length++;
i++;
}
for (int r = 0; r < 1000; r++)
printf("%s ", rev[r]);
return 0;
}
fix like this
#include <stdio.h>
int main(void) {
char str[1000];
char rev[1000][1000];
puts("Enter text:");
fgets(str, sizeof str, stdin);//Use fgets instead of gets. It has already been abolished.
int r = 0;
int k = 0;
for(int i = 0; str[i] != '\0'; ++i){
if (str[i] == ' ' || str[i] == '\n'){//is delimiter
if(k != 0){
rev[r++][k] = '\0';//add null-terminator and increment rows
k = 0;//reset store position
}
} else {
rev[r][k++] = str[i];
}
}
if(k != 0)//Lastly there was no delimiter
rev[r++][k] = '\0';
puts("So the words are:");
for (int i = 0; i < r; i++){
printf("%s", rev[i]);
if(i < r - 2)
printf(", ");
else if(i == r - 2)
printf(" and ");
}
return 0;
}
Replace you declaration
char rev[1000][1000];
with
char * rev[1000]; // We will need pointers only
int i = 0; // Index to previous array
and all your code after
puts( "Enter text:" );
with this:
fgets( str, 998, stdin ); // Safe way; don't use gets(str)
const char delim[] = ",; "; // Possible delimiters - comma, semicolon, space
char *word;
/* Get the first word */
word = strtok( str, delim );
rev[i++] = word;
/* Get the next words */
while( word != NULL )
{
word = strtok( NULL, delim );
rev[i++] = word;
}
/* Testing */
for (int r = 0; r < i - 1; r++)
printf( "%s\n", rev[r] );
return 0
}
As you can see, all dirty work is done with the strtok() function ("string to tokens") which walks through other and other words ("tokens"), recognizing them as delimited by one or more characters from the string delim.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int count_spaces(char *str)
{
if (str == NULL || strlen(str) <= 0)
return (0);
int i = 0, count = 0;
while (str[i])
{
if (str[i] == ' ')
count++;
i++;
}
return (count);
}
int count_char_from_pos(char *str, int pos)
{
if (str == NULL || strlen(str) <= 0)
return 0;
int i = pos, count = 0;
while (str[i] && str[i] != ' ')
{
count++;
i++;
}
return count;
}
char **get_words(char *str)
{
if (str == NULL || strlen(str) <= 0)
{
printf("Bad string inputed");
return NULL;
}
int i = 0, j = 0, k = 0;
char **dest;
if ((dest = malloc(sizeof(char*) * (count_spaces(str) + 1))) == NULL
|| (dest[0] = malloc(sizeof(char) * (count_char_from_pos(str, 0) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
while (str[i])
{
if (str[i] == ' ') {
dest[j++][k] = '\0';
if ((dest[j] = malloc(sizeof(char) * (count_char_from_pos(str, i) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
k = 0;
}
else {
dest[j][k++] = str[i];
}
i++;
}
dest[j][k] = 0;
dest[j + 1] = NULL;
return dest;
}
int main(void) {
char *line = NULL;
size_t n = 0;
getline(&line, &n, stdin);
printf("%s\n", line);
line[strlen(line) - 1] = 0;
printf("%s\n", line);
char **tab = get_words(line);
int i = 0;
while (tab[i])
{
printf("%s\n", tab[i++]);
}
}
here is a long but fully working example
get the user input
then send it to get_words function. It will get the number of words, the number of characters for each words, allocate everything in memory and writes chars then return it. You get a char ** and prints it just tested it it works
If you wish to split a string into an array of strings, you should consider the strtok function from #include <string.h>. The strtok function will the split the string on the given delimiter(s). For your case, it would the " ".
Using the strtok example from Tutorials Point:
#include <string.h>
#include <stdio.h>
int main(){
char str[80] = "This is - www.tutorialspoint.com - website";//The string you wish to split
const char s[] = "-";//The thing you want it to split from. But there is no need to this.
char *token;//Storing the string
/* get the first token */
token = strtok(str, s);//Split str one time using the delimiter s
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );//Print the string
token = strtok(NULL, s);//Split the string again using the delimiter
}
return(0);
}

Program that returns words that ends and starts with the same letter

I have problem with my alignement. This time I want my program to return words that ends and starts with the same letter. I've wrote something like this, but it seems to return random words.
#include <stdio.h>
#include <string.h>
void main()
{
char str[100];
int i, t, j, len;
printf("Enter a string : ");
scanf("%[^\n]s", str);
len = strlen(str);
str[len] = ' ';
for (t = 0, i = 0; i < strlen(str); i++)
{
if ((str[i] == ' ') && (str[i - 1] == str[0]))
{
for (j = t; j < i; j++)
printf("%c", str[j]);
t = i + 1;
printf("\n");
}
else
{
if (str[i] == ' ')
{
t = i + 1;
}
}
}
}
You can use strtok to split the strings from stdin, then apply a letter checker on each parsed word one at a time.
Something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXCHAR 100
int is_start_end(char *word);
void exit_if_null(void *ptr, const char *msg);
int
main(void) {
char str[MAXCHAR];
char *word;
char **all_words;
int words_size = 1, word_count = 0;
int i, found;
all_words = malloc(words_size * sizeof(*all_words));
exit_if_null(all_words, "initial Allocation");
printf("Enter words(enter empty line to terminate):\n");
while (fgets(str, MAXCHAR, stdin) != NULL && strlen(str) != 1) {
word = strtok(str, " \n");
while (word !=NULL) {
if (words_size == word_count) {
words_size *= 2;
all_words = realloc(all_words, words_size * sizeof(*all_words));
exit_if_null(all_words, "Reallocation");
}
all_words[word_count] = malloc(strlen(word)+1);
exit_if_null(all_words[word_count], "Initial Allocation");
strcpy(all_words[word_count], word);
word_count++;
word = strtok(NULL, " \n");
}
}
printf("Words that have equal first and last letters:\n");
found = 0;
for (i = 0; i < word_count; i++) {
if (is_start_end(all_words[i])) {
found = 1;
printf("%s\n", all_words[i]);
}
free(all_words[i]);
all_words[i] = NULL;
}
if (found == 0) {
printf("None Found\n");
}
free(all_words);
all_words = NULL;
return 0;
}
int
is_start_end(char *word) {
int len;
len = strlen(word);
if ((len == 1) || (tolower(word[0]) == tolower(word[len-1]))) {
return 1;
}
return 0;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
This line removes the null terminator of the string:
len = strlen(str);
str[len] = ' ';
thus the string no longer exists, what is left is just an ordinary array of characters.
The next call to strlen, in the body of the for loop, will cause undefined behavior.

how to perform reversing a sentence Word by Word in C?

#include <stdio.h>
int main(void)
{
int i,j;
int wordstart = -1;
int wordend = -1;
char words[]= "this is a test";
char temp;
// Reverse each word
for (i = 0; i < strlen(words); ++i)
{
wordstart = -1;
wordend = -1;
if(words[i] != ' ')
wordstart = i;
for (j = wordstart; j < strlen(words); ++j)
{
if(words[j] == ' ')
{
wordend = j - 1;
break;
}
}
if(wordend == -1)
wordend = strlen(words);
for (j = wordstart ; j <= (wordend - wordstart) / 2; ++j)
{
temp = words[j];
words[j] = words[wordend - (j - wordstart)];
words[wordend - (j - wordstart)] = temp;
}
i = wordend;
printf("reversed string is %s:", words);
}
}
I tried in this way but i am getting this output:
siht is a test
my expected output is:
test a is this
I would appreciate if some one could come with a different approach for which time complexity is very less or correct me if it is the right approach. Thanks
Perhaps this belongs on the code review site instead?
Your approach seems very efficient to me (except that I would only call strlen(words) once and save the result in a register).
Two possible bugs look like:
wordend = strlen(words);
should be
wordend = strlen(words)-1;
and
for(j = wordstart ; j <= (wordend - wordstart) / 2 ; ++j) {
should be
for(j = wordstart ; j <= (wordend + wordstart) / 2 ; ++j) {
Final code looks like (with some extra {}):
#include <stdio.h>
int main(int argc,char *argv[])
{
int i,j;
char words[]= "this is a test";
int L=strlen(words);
// Reverse each word
for(i = 0; i < L; ++i) {
int wordstart = -1;
int wordend = -1;
if(words[i] != ' ')
{
wordstart = i;
for(j = wordstart; j < L; ++j) {
if(words[j] == ' ') {
wordend = j - 1;
break;
}
}
if(wordend == -1)
wordend = L-1;
for(j = wordstart ; j <= (wordend + wordstart) / 2 ; ++j) {
char temp = words[j];
words[j] = words[wordend - (j - wordstart)];
words[wordend - (j - wordstart)] = temp;
}
i = wordend;
}
}
printf("reversed string is %s:",words);
return 0;
}
You can create a double linked list as a base data structure. Then, iterate through the words and insert them in the list as you find them.
When you reach the end of the sentence, simply traverse the list backwards and print the words as you go through them
Simply we can just use a n*1 2D character array tailored to suit our needs!!!
#include <stdlib.h>
int main()
{
char s[20][20];
int i=0, length=-1;
for(i=0;;i++)
{
scanf("%s",s[i]);
length++;
if(getchar()=='\n')
break;
}
for(i=length;i>=0;i--)
printf("%s ",s[i]);
return 0;
}
Start tokenizing the line from the last character and continue to the first character. Keep one pointer anchored at the base of the current word, and another pointed which will decrease while a word start is not found. When you find a word start while scanning like this, print from the word start pointer to the word end anchor. Update the word end anchor to the previous character of the current word start char.
You might want to skip the blankspace characters while scanning.
UPDATE
This is a quick implementation:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_BUF 256
void show_string (char *str, int i, int n)
{
while (i <= n)
{
printf ("%c", str[i]);
i++;
}
}
int main (void)
{
char str[MAX_BUF];
int end_anchor, start_ptr;
int state;
printf ("\nEnter a string: ");
scanf (" %[^\n]", str);
start_ptr = strlen (str) - 1;
end_anchor = start_ptr;
state = 0;
while (start_ptr >= -1)
{
switch (state)
{
case 0:
if ((!isspace (str[start_ptr]) && (start_ptr >= 0)))
{
start_ptr--;
}
else
{
state = 1;
}
break;
case 1:
show_string (str, start_ptr + 1, end_anchor);
state = 2;
start_ptr--;
printf (" ");
break;
case 2:
if (!isspace (str[start_ptr]))
{
state = 0;
end_anchor = start_ptr;
}
else
{
start_ptr--;
}
break;
}
}
printf ("\n");
return 0;
}
The end_anchor points to each end word, and the start_ptr finds the start of the word of which the end is held by end_anchor. When we find a word start (by blankspace characters or start_ptr = -1), we print all the characters from start_ptr + 1 to end_anchor. The + 1 is because of the implementation: start_ptr points to the blankspace character, and the print routine will print all the characters from i to n. Once we have detected one blank space we print it and we skip adjacent blankspaces (in case 2) and preserve only one which is manually printed. Once a non blankspace is detected, we have got another word end, for which we set the end_anchor to this index in the case 2, and set state = 0 , so that we can search for the word start again.
if(words[i] != ' ')
wordstart = i;
This statement what about the else part? if words[i] == ' ', and wordstart remains -1.
So maybe try to use:
while (words[i] && words[i] == ' ') ++i;
if (!words[i])
break;
wordstart = i;
Then you should output the result out of the i loop.
Finally, if you want to get the result you expected, you should reverse the whole sentence once more, with the way you used in the loop.
I would use write function similar to strrchr for finding last occurence of ' ', if its found print word that follows, rewrite this ' ' with '\0' and repeat it in loop till no more words are found. At the end I would print the content of this string again because there is most likely no ' ' before the first word.
I would write own function instead of strrchr because strrchr calculates the lenght of the given string, which is redundant in this case. This length doesn't have to be calculated more than once.
Here's the code:
char* findLastWord(char* str, int* len)
{
int i;
for (i = *len - 1; i >= 0; --i)
{
if (str[i] == ' ')
{
str[i] = '\0';
if (i < *len - 1)
{
*len = i - 1;
return &str[i + 1];
}
}
}
return NULL;
}
int main (int argc, char *argv[])
{
char str[] = " one two three four five six ";
int len = strlen(str);
char* lastWord = findLastWord(str, &len);
while (lastWord != NULL)
{
printf("%s\n", lastWord);
lastWord = findLastWord(str, &len);
}
if (len > 1)
printf("%s\n", str);
return 0;
}
output:
six
five
four
three
two
one
Hope this helps ;)
#include<stdio.h>
#include<string.h>
void reverse(char *str, size_t len)
{
char tmp;
size_t beg, end;
if (len <=1) return;
for (beg=0,end=len; beg < --end ; beg++) {
tmp = str[beg];
str[beg] = str[end];
str[end] = tmp;
}
}
int main(void)
{
char sentence[] = "one two three four five";
size_t pos, len;
printf("Before:%s\n",sentence);
for (pos = len= 0; sentence[pos]; pos += len) {
pos += strspn( sentence+pos, " \t\n" );
len = strcspn( sentence+pos, " \t\n" );
reverse ( sentence + pos, len );
}
reverse ( sentence , pos );
printf("After:%s\n",sentence);
return 0;
}
#include <iostream>
#include <string>
using namespace std;
char* stringrev(char s[], int len)
{
char *s1 = (char*)malloc(len+1);
int i=0;
while (len>0)
{
s1[i++] = s[--len];
}
s1[i++] = '\0';
return s1;
}
void sentrev(char s[], int len)
{
int i=0; int j=0;
char *r = (char*)malloc(len+1);
while(1)
{
if(s[j] == ' ' || s[j] == '\0')
{
r = stringrev(s+i, j-i);
i = j+1;
cout<<r<<" ";
}
if (s[j] == '\0')
break;
j++;
}
}
int main()
{
char *s = "this is a test";
char *r = NULL;
int len = strlen(s);
cout<<len<<endl;
r = stringrev(s, len);
cout<<r<<endl;
sentrev(r, len);
return 0;
}
The above code snap reverse the sentence, using char *r
and printing cout<
#include<stdio.h>
#include<conio.h>
#include<string.h>
int main()
{
char st[50], rst[50];
printf("Enter the sentence...\n");
gets(st);
int len=strlen(st), p;
int j=-1,k;
p=len;
for(int i=(len-1); i>=0; i--)
{
//searching for space or beginning
if(st[i]==' ')
{
//reversing and storing each word except the first word
for(k=i+1;k<p;k++)
{
//printf("%c",st[k]);
rst[++j]=st[k];
}
j++;
rst[j]=' ';
printf("\n");
p=i;
}
else if(i==0)
{
//for first word
for(k=i;k<p;k++)
{
//printf("%c",st[k]);
rst[++j]=st[k];
}
}
}
printf("Now reversing the sentence...\n");
puts(rst);
return 0;
}
Use a main for loop to traverse till the end of the sentence:
Copy the letters in a string until you find a space.
now call add#beginning function and in that function add the string each time you pass a string to the linked list.
print the contents of the linked list with a space inbetween to get the expected output
My code,just traverse from the last and if you find a space print the characters before it,now change the end to space-1;This will print till the second word,finally just print the first word using a single for loop.Comment for alter approach.
Program:
#include<stdio.h>
int main()
{
char str[200];
int i,j,k;
scanf("%[^\n]s",&str);
for(i=0;str[i]!='\0';i++);
i=i-1;
for(j=i;j>=0;j--)
{
if((str[j])==' ')
{
for(k=j+1;k<=i;k++)
{
printf("%c",str[k]);
}
i=j-1;
printf(" ");
}
}
for(k=0;k<=i;k++)
{
printf("%c",str[k]);
}
}
using stack
#include <iostream>
#include <stdio.h>
#include <stack>
int main()
{
std::stack<string> st;
char *words= "this is a test";
char * temp = (char *)calloc(1, sizeof(*temp));
int size1= strlen(words);
int k2=0;
int k3=0;
for(int i=0;i<=size1;i++)
{
temp[k2] = words[i];
k2++;
if(words[i] == ' ')
{
k3++;
if(k3==1)
temp[k2-1]='\0';
temp[k2]='\0';
st.push(temp);
k2=0;
}
if(words[i] == '\0')
{
temp[k2]='\0';
st.push(temp);
k2=0;
break;
}
}
while (!st.empty())
{
printf("%s",st.top().c_str());
st.pop();
}

Resources