Sorting strings doesn't work properly - c

I have rjecnik.txt file that looks like this
mate sime, jure
stipica gujo, prvi
ante mirkec
goran maja, majica
avion kuca, brod, seoce
amerika, neka, zemlja, krcma
brodarica, zgrada, zagreb
zagreb split
zadar rijeka
andaluzija azija
I need to order lines alphabetically (not words) and my program produces this result which is not correct:
andaluzija azijamate sime, jure
amerika, neka, zemlja, krcma
brodarica, zgrada, zagreb
ante mirkec
avion kuca, brod, seoce
goran maja, majica
stipica gujo, prvi
zadar rijeka
zagreb split
Press [Enter] to close the terminal ...
When I use non ascii character like kuća for kuca or krčma for krcma it produces this result (all wrong)
andaluzija azijamate sime, jure
amerika, neka, zemlja, krŔma
brodarica, zgrada, zagreb
ante mirkec
avion kuŠa, brod, seoce
goran maja, majica
stipica gujo, prvi
zadar rijeka
zagreb split
Press [Enter] to close the terminal ...
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int ch, nl = 1, min, lenght1, lenght2, lenght;//ch will hold characters, min is for selection sort, lenght holds value of strlen for determine wthat line is longer
FILE * fp;// FILE pointer
char * lines[1000];//that will dynamically hold strings for lines
char * temp;//for lines swaping
if((fp = fopen("C:\\Users\\don\\Documents\\NetBeansProjects\\proba2\\dist\\Debug\\MinGW-Windows\\rjecnik.txt", "r")) == NULL)//I had to temporarily put full path to rjecnik.txt
{
printf("Can't open file...");
exit(1);
}
while((ch = getc(fp)) != EOF)//count lines
{
if(ch == '\n')
nl++;
}
int i, j;
for (i = 0; i < nl; i++)
lines[i] = malloc(1000);//create array of string size value of nl
fseek(fp, 0L, SEEK_SET);//go to start of file
i = 0;
j = 0;
while((ch = getc(fp)) != EOF)//fill arrays of string
{
lines[i][j] = ch;
j++;
if(ch == '\n')
{
j = 0;
i++;
}
}
for(i = 0; i < nl - 1; i++)//selection sort doesn't work properly
{
min = i;//min is i
for(j = i + 1; j < nl; j++)//for number of lines(nl) times
{
lenght1 = strlen(lines[i]);//find what string is longer and lenght is smaller one
lenght2 = strlen(lines[j]);
if(lenght1 < lenght2)
lenght = lenght1;
else
lenght = lenght2;
if(strncmp(lines[i], lines[j], lenght) > 0 )//compare two strings
min = j;//if second string is alphabetically smaller min is j
}
temp = lines[i];// swapping
lines[i] = lines[min];
lines[min] = temp;
}
for(i = 0; i < nl; i++ )//printing to console
{
lenght1 = strlen(lines[i]);
for(j = 0; j < lenght1; j++ )
{
putchar(lines[i][j]);
}
}
return 0;
}
Now program crashes at the end when I add this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int ch, nl = 1, min, lenght1, lenght2, lenght;//ch will hold characters, min is for selection sort, lenght holds value of strlen for determine wthat line is longer
FILE * fp;// FILE pointer
char * lines[1000];//that will dynamically hold strings for lines
char * temp;//for lines swaping
if((fp = fopen("C:\\Users\\don\\Documents\\NetBeansProjects\\proba2\\dist\\Debug\\MinGW-Windows\\rjecnik.txt", "r")) == NULL)//I had to temporarily put full path to rjecnik.txt
{
printf("Can't open file...");
exit(1);
}
while((ch = getc(fp)) != EOF)//count lines
{
if(ch == '\n')
nl++;
}
int i, j;
for (i = 0; i < nl; i++)
lines[i] = malloc(1000);//create array of string size value of nl
fseek(fp, 0L, SEEK_SET);//go to start of file
i = 0;
j = 0;
while((ch = getc(fp)) != EOF)//fill arrays of string
{
lines[i][j] = ch;
j++;
if(ch == '\n')
{
j = 0;
i++;
}
}
for(i = 0; i < nl - 1; i++)//selection sort doesn't work properly
{
min = i;//min is i
for(j = i + 1; j < nl; j++)//for number of lines(nl) times
{
lenght1 = strlen(lines[i]);//find what string is longer and lenght is smaller one
lenght2 = strlen(lines[j]);
if(lenght1 < lenght2)
lenght = lenght1;
else
lenght = lenght2;
if(strncmp(lines[min], lines[j], lenght ) > 0 )//compare two strings
min = j;//if second string is alphabetically smaller min is j
}
temp = lines[i];// swapping
lines[i] = lines[min];
lines[min] = temp;
}
for(i = 0; i < nl; i++ )//printing to console
{
lenght1 = strlen(lines[i]);
for(j = 0; j < lenght1; j++ )
{
putchar(lines[i][j]);
}
}
for (i = 0; i < 100; i++)//Program crashes here
free(lines[i]);
return 0;
}

1.- You must initialize lines to 0 after malloc so strlen works properly.
2.- Compare lines[j] with lines[min]
3.- Don't forget free lines

You're always comparing lines[j] to lines[i], but you should be comparing it to lines[min].

If this isn't you learning about how to sort and get input, c provides qsort() and fgets(), so you could
int strsort(const void *a, const void *b)
{
char *const*astr=a, *const*bstr=b;
return strcmp(*astr, *bstr);
}
main()
{
FILE*f = fopen(...);
char (*arr)[1000] = malloc(1000*1000);
int x;
for(x=0;x<1000 && fgets(1000, arr[x], f);x++)
arr[x][strlen(arr[x])-2] = '\0'; //strip newlines
qsort(arr, x, 1, strsort);
int i;
for(i=0; i<x; i++)
printf("%s\n", arr[x]);
}
It's much clearer what you're doing this way.

Minor nitpick:
lenght1 = strlen(lines[i]);
lenght2 = strlen(lines[j]);
if(lenght1 < lenght2)
lenght = lenght1;
else
lenght = lenght2;
if(strncmp(lines[i], lines[j], lenght) > 0 )
... ;
You don't need this: strcmp() stops when either of the strings terminates, whichever comes first. In your case, you need to compare one more character (the NUL), like
strncmp( lines[i], lines[j], lenght+1)
, otherwise "apple" and "apples" would compare equal (because only the first five characters would be compared). But the "normal" form:
strcmp(lines[i], lines[j])
does exactly what you want.

Related

Array not being fully parsed in C program

I am trying to build a program that parses an array of chars from input and then returns a formatted omitting extra whites spaces.
#include <stdio.h>
# include <ctype.h>
/* count charecters in input; 1st version */
int main(void)
{
int ch, outp=0;
char str[1000], nstr[1000];
/* collect the data string */
while ((ch = getchar()) != EOF && outp < 1000){
str[outp] = ch;
outp++;
}
for (int j = 0; j < outp-1; j++){
printf("%c",str[j]);
}
printf("\n");
for (int q = 0; q < outp-1; q++)
{
if (isalpha(str[q]) && isspace(str[q+1])){
for(int i = 0; i < outp; i++){
if (isspace(str[i]) && isspace(i+1)){
continue;
}
nstr[i] = str[i];
}
}
}
printf("\n");
printf("Formated Text: ");
for (int i = 0; i < outp-1; i++){
printf("%c", nstr[i]);
}
//putchar("\n");c
// printf("1");
return 0;
}
Here is my code. The array is never fully parsed, the end is usually omitted, odd chars show up and past attempts have yielded a not fully parsed array, Why?
This is exercise 1-9 from "the C programming language".
a) You need to use an additional index variable while copying the characters from str to nstr. Do something like -
for(int i = 0, j = 0; i < outp -1; i++){
if (isspace(str[i]) && isspace(i+1)){
continue;
}
nstr[j++] = str[i];
}
b) While you are printing nstr, you are using the length of the original string str. The length of nstr will be less than that of str since you have removed the spaces.
You need to find the length of nstr now or use i < strlen(nstr) -1 in the condition.

Reversing the order of words backwards in a string

Sorry for such a mediocre question, but I ran into what seems to be a tiny problem, but simply can't get over it. For my task I have to take a line of string from a file, and put it into another file backwards, for example:
one two three
four five six
would be
three two one
six five four
My problem is, is that I'm getting
three two one
si five four
So basically the flaw is that there is a space character at the beginning of each line and the last letter of the last word is always missing. Here's my reverse function:
void reverse(char input[], int length, char output[]) {
char space = 32;
input[length - 1] = space;
int value = 0;
int i, k = 0, j;
for (i = 0; i <= length; i++) {
if (input[i] == space) {
for (j = i - 1; j >= k; j--, value++) {
output[value] = input[j];
}
if (j == -1) {
output[value] = space;
value++;
}
k = i;
}
}
char c = 0;
for (int i = 0, j = length - 1; i <= j; i++, j--) {
c = output[i];
output[i] = output[j];
output[j] = c;
}
}
What I'm doing is first reversing each word by character, and then the whole line. If someone could help me find the last bits that I've missed I would greatly appreciate it.
The flaws come from your approach:
why do you force a space at offset length - 1? If you read the line with fgets(), there is probably a newline ('\n') at the end of the line, but it might be missing at the end of the input, which would explain the x getting overwritten on the last line.
you should not modify the input buffer.
Here is a simplified version, along with a simple main function:
#include <stdio.h>
#include <string.h>
void reverse(const char *input, int length, char *output) {
int i, j, k, v;
for (i = k = v = 0;; i++) {
if (i == length || input[i] == ' ') {
for (j = i; j-- > k; v++) {
output[v] = input[j];
}
for (; i < length && input[i] == ' '; i++) {
output[v++] = ' ';
}
if (i == length) {
output[v] = '\0';
break;
}
k = i;
}
}
for (i = 0, j = length - 1; i < j; i++, j--) {
char c = output[i];
output[i] = output[j];
output[j] = c;
}
}
int main() {
char input[256];
char output[256];
while (fgets(input, sizeof input, stdin)) {
reverse(input, strcspn(input, "\n"), output);
puts(output);
}
return 0;
}
Output:
three two one
six five four
Here is a simpler reverse function that operates in one pass:
#include <string.h>
void reverse(const char *input, int length, char *output) {
int i, j, k, v;
for (i = k = 0, v = length;; i++) {
if (i == length || input[i] == ' ') {
for (j = i; j-- > k;) {
output[--v] = input[j];
for (; i < length && input[i] == ' '; i++) {
output[--v] = ' ';
}
if (v == 0) {
output[length] = '\0';
break;
}
k = i;
}
}
}
Replace input[length - 1] = space; with input[length] = space;

Detecting EOF of a txt File in C

I wrote this code which reads every char of my text and puts it into my char array. My Problem is that the end of the file is not detected and so the fscanf() returns after the end of the text every time the last char until my array is filled. How can I prevent that? I am programming in C.
My Code:
int main() {
char array[50][50];
char buff;
FILE *cola = fopen("C:/Users/danie/Desktop/cola.txt", "r");
for (int i = 0; i < 50; i++) {
for (int k = 0; k < 50; k++) {
fscanf(cola, "%c", &buff);
array[i][k] = buff;
}
}
fclose(cola);
for (int i = 0; i < 50; i++) {
for (int k = 0; k < 50; k++) {
printf("%c", array[i][k]);
}
}
return 0;
}
Thank you for your help.
fscanf() returns the number of successful conversions. You should test the return value and also handle newline characters specifically:
#include <stdio.h>
int main(void) {
char array[50][50];
char buff;
FILE *cola = fopen("C:/Users/danie/Desktop/cola.txt", "r");
if (cola == NULL) {
return 1;
}
for (int i = 0; i < 50; i++) {
for (int k = 0; k < 50; k++) {
if (fscanf(cola, "%c", &buff) != 1 || buff == '\n') {
array[i][k] = '\0';
break;
}
array[i][k] = buff;
}
}
fclose(cola);
for (int i = 0; i < 50; i++) {
for (int k = 0; k < 50 && array[i][k] != '\0'; k++) {
printf("%c", array[i][k]);
}
printf("\n");
}
return 0;
}
The code can be simplified if you use getc() instead of fscanf() to read bytes from the file:
#include <stdio.h>
int main(void) {
char array[50][51];
int c, i, k, n;
FILE *cola = fopen("C:/Users/danie/Desktop/cola.txt", "r");
if (cola == NULL) {
return 1;
}
for (n = 0; n < 50; n++) {
for (k = 0; k < 50; k++) {
if ((c = getc(cola)) == EOF || c == '\n') {
break;
}
array[n][k] = c;
}
array[n][k] = '\0';
if (c == EOF && k == 0)
break;
}
fclose(cola);
for (i = 0; i < n; i++) {
puts(array[i]);
}
return 0;
}
Replace:
for (int i = 0; i < 50; i++) {
for (int k = 0; k < 50; k++) {
fscanf(cola, "%c", &buff);
array[i][k] = buff;
}
}
with:
for (int i = 0; i < 50; i++) {
for (int k = 0; k < 50; k++) {
int c = getc(cola);
if (c == EOF)
break;
array[i][k] = c;
}
}
Since buff is then unused, don't define it. Note that the return type of getc() is an int, not just a char. Always check the I/O function for success/failure. In your original code, you don't even check whether the I/O operation succeeds, which makes detecting EOF impossible.
Note that this code makes a number of assumptions that may or may not be justifiable. For example, you assume each line in the file consists of 49 characters plus a newline; you also assume you'll never need to print the information as a 'string' (your existing code does not; it prints character by character, so it is 'safe').
You might want to describe the input as:
Read up to 50 lines with up to 49 characters plus a newline in each line, storing the result in the variable array with each line being a null-terminated string.
This is more resilient to common problems (short lines, long lines, not enough lines). The code for that might be:
enum { LINE_LEN = 50, NUM_LINES = 50 };
char array[NUM_LINES][LINE_LEN];
int i;
for (i = 0; i < LINE_LEN; i++)
{
int c;
int k;
for (k = 0; k < LINE_LEN; k++)
{
c = getc(cola);
if (c == EOF || c == '\n')
break;
if (k == LINE_LEN - 1)
{
/* Too long - gobble excess */
while ((c = getc(cola)) != EOF && c != '\n')
;
break;
}
array[i][k] = c;
}
array[i][k] = '\0';
if (c == EOF)
break;
}
int num_lines = i; // You have num_lines lines of data in your array
I found one version of the Coca Cola™ ASCII art image at https://www.ascii-code.com/ascii-art/logos/coca-cola.php which looks similar to what you have in your images, but there are many other sources and variants:
__ ___ __ .ama ,
,d888a ,d88888888888ba. ,88"I) d
a88']8i a88".8"8) `"8888:88 " _a8'
.d8P' PP .d8P'.8 d) "8:88:baad8P'
,d8P' ,ama, .aa, .ama.g ,mmm d8P' 8 .8' 88):888P'
,d88' d8[ "8..a8"88 ,8I"88[ I88' d88 ]IaI" d8[
a88' dP "bm8mP8'(8'.8I 8[ d88' `" .88
,88I ]8' .d'.8 88' ,8' I[ ,88P ,ama ,ama, d8[ .ama.g
[88' I8, .d' ]8, ,88B ,d8 aI (88',88"8) d8[ "8. 88 ,8I"88[
]88 `888P' `8888" "88P"8m" I88 88[ 8[ dP "bm8m88[.8I 8[
]88, _,,aaaaaa,_ I88 8" 8 ]P' .d' 88 88' ,8' I[
`888a,. ,aadd88888888888bma. )88, ,]I I8, .d' )88a8B ,d8 aI
"888888PP"' `8""""""8 "888PP' `888P' `88P"88P"8m"
This file's longest line is the first at 67 characters plus newline; the shortest is 61 characters plus newline. The file only has 13 lines and 845 characters (LF line endings) in total. Thus, your program is ill-equipped to deal with this particular data file. It looks for 2,500 characters, and won't get them.
My complete test code was rigged to read from standard input, rather than a fixed file name.
#include <stdio.h>
int main(void)
{
FILE *cola = stdin;
enum { LINE_LEN = 80, NUM_LINES = 50 };
char array[NUM_LINES][LINE_LEN];
int i; // Need value of i after loop
for (i = 0; i < NUM_LINES; i++)
{
int c; // Need value of c after loop
int k;
for (k = 0; k < LINE_LEN; k++)
{
c = getc(cola);
if (c == EOF || c == '\n')
break;
if (k == LINE_LEN - 1)
{
/* Too long - gobble excess */
while ((c = getc(cola)) != EOF && c != '\n')
;
break;
}
array[i][k] = c;
}
array[i][k] = '\0';
if (c == EOF)
break;
}
int num_lines = i; // You have num_lines lines of data in your array
for (i = 0; i < num_lines; i++)
puts(array[i]);
return 0;
}
I tested it on the data file shown, with an empty line at the end, and with a couple of lines containing more than 79 characters after the blank line. It handled all those special cases correctly. Note that handling user input is hard; handling perverse user input is harder. The code is less compact. You could change the rules and then change the code to match. I'm not sure this is the most minimal way to code this; it does work, however. It might be better to have a function to handle the inner input loop; the outer loop could test the return value from that function. This would cut down on the special case handling.
#include <assert.h>
#include <limits.h>
#include <stdio.h>
static int read_line(FILE *fp, size_t buflen, char *buffer)
{
assert(buflen < INT_MAX);
int c; // Need value of c after loop
size_t k; // Need value of k after loop
for (k = 0; k < buflen; k++)
{
if ((c = getc(fp)) == EOF || c == '\n')
break;
if (k == buflen - 1)
{
/* Too long - gobble excess */
while ((c = getc(fp)) != EOF && c != '\n')
;
break;
}
buffer[k] = c;
}
buffer[k] = '\0';
return (k == 0 && c == EOF) ? EOF : (int)k;
}
int main(void)
{
enum { LINE_LEN = 80, NUM_LINES = 50 };
char array[NUM_LINES][LINE_LEN];
int i;
for (i = 0; i < NUM_LINES; i++)
{
if (read_line(stdin, LINE_LEN, array[i]) == EOF)
break;
}
int num_lines = i;
for (i = 0; i < num_lines; i++)
puts(array[i]);
return 0;
}
This produces the same output from the same input as the previous version.
int main() {
//char array[50][50];
char buff;
int t;
FILE *cola = fopen("C:/Users/danie/Desktop/cola.txt", "r");
if (cola == NULL)
{
printf("Cannot open file \n");
exit(0);
}
while (1) {
t = fgetc(cola);
if (t == EOF)
break;
buff = t;
printf("%c", buff);
}
fclose(cola);
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

Reversing array logic in C not working properly

I am trying to read the input to my program (a string of chars) and invert the order of the words that are in it.
For example, if I were to pass my program ABC DEF GHI JKL it would output JKL GHI DEF ABC. I am using the whitespace as separators.
My code:
char toReverse[1000];
char outputArray[1000];
int charCount = //Size of the toReverse array. Varies on the input
//It is the total number of chars stored in the array
...
int i;
int tempCharCount = charCount;
int wordSize = 0;
int outputIndex = 0;
int sentenceIndex = 0;
int charStep = 0;
for(i = charCount-1; i>=0; i--){
if(toReverse[i] == ' '){
int j;
sentenceIndex = tempCharCount - wordSize;
for(j = 0; j<charStep; j++){
outputArray[outputIndex++] = toReverse[sentenceIndex++];
}
outputArray[outputIndex] = ' ';
outputIndex++;
charStep = 0;
}
wordSize++;
charStep++;
}
There is a flaw in my code. I do know why this happens though. For example, if I were to pass as input ABC DEF GHI, it will only output GHI DEF. This is because whenever the outer for loop reaches index 0 of my toReverse array, since it is not a space ' ', it does not do the if(toReverse[i]) inner for(j = 0; j<charStep; j++) since the condition is not met.
Do you have any advice regarding to the logic? I have tried reversing my logic, such as if(toReverse[i] != ' ') but it brings more problems than it solves.
Thanks for your advice and comments!
Cheers
Edit 1
I am reading my input from a file By the way!
Update 1
Here I am basically trying to open various files and read chars from them
int main(int argc, char * argv[])
{
int i = 1;
FILE * fp = NULL;
if(1==argc){
do_read(stdin);
}else{
// cycle through all files in command line arguments and read them
for (i=1; i < argc; i++) {
if ((fp = fopen(argv[i], "r")) == NULL) {
printf("Failed to open file.\n");
}
else {
do_read(fp);
fclose(fp);
}
}
}
//printf("\n");
//printf("\n");
printf("%i",charCount);
return 0;
}
sample
#include <stdio.h>
#include <string.h>
void proc_rev(char toReverse[], char outputArray[]){
int charCount = strlen(toReverse);
int i;
int tempCharCount = charCount;
int wordSize = 0;
int outputIndex = 0;
int sentenceIndex = 0;
int charStep = 0;
for(i = charCount-1; i>=0; i--){
if(toReverse[i] == ' '){
int j;
sentenceIndex = tempCharCount - wordSize;
for(j = 0; j<charStep; j++){
outputArray[outputIndex++] = toReverse[sentenceIndex++];
}
outputArray[outputIndex] = ' ';
outputIndex++;
charStep = 0;
}
wordSize++;
charStep++;
}
outputArray[outputIndex] = '\0';
}
int main(void){
FILE *fp = stdin;
char toReverse[1000] = " ";
char outputArray[1000];
while(1 == fscanf(fp, "%998[^\n]%*c", &toReverse[1])){
proc_rev(toReverse, outputArray);
puts(outputArray);
}
return 0;
}
void do_read(FILE *fp){
char toReverse[1000] = " ";
char outputArray[1000];
while(1 == fscanf(fp, "%998[^\n]%*c", &toReverse[1])){
proc_rev(toReverse, outputArray);
puts(outputArray);
}
}
This code is not tested but basic idea is reversing the whole string once and then reverse it word by word. idea is correct, implementation may have bugs
void swap(char* s, int i, int j) {
char tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
void rev(char* stirng, int start, int len) {
for (int i=0; i<len/2; ++i) {
swap(string, i, len-i-1);
}
}
int main() {
char* string = read from file
int len = strlen(string);
rev(string, 0, len);
for (int i=0; i<len;) {
int l = 0;
int j=i;
while (j<len && string[j]!=' ') ++j;
rev(string, i, j-i);
i=j+1;
}
}
The current logic reverses individual words from last to second word. However to reverse the first word you will have to add a check apart from
if(toReverse[i] == ' ')
as the first character need not be a space.
A separate check can be used when counter 'i' reaches zero, i.e. first character

Resources