Printing lines from a text file in reverse order - c

I am trying to read in the Constitution as a text file from the command line into my program to print out the lines in reverse order. My for loop looks like this:
for(int i = 0; i >= 0; i--) {
if(strings[i] == '\0') //counts through array until it finds a line break
{
break;
}
printf("%s", strings[i]);
}
When the program runs, the only thing that prints is the first line of the Constitution. If I modify my for loop to increment i, the program runs smoothly and outputs the Constitution like normal, and therefore I believe my entire problem is summed up in this for loop. This is the rest of my program for reference.
int clearBuffer() {
char junk;
while((junk = getchar()) != feof(stdin) && junk != '\n');
return 0;
}
int getAline(char ** bufferPointer, int * sizePointer){
char * buffer = *bufferPointer;
int count = 0;
int size = *sizePointer;
while(!feof(stdin)){
if(count >= size - 1){
char * tempBuffer = (char * )malloc(size * 10);
//strcpy(tempBuffer, buffer );
for (int i = 0; i < size; i++){
tempBuffer[i] = buffer[i];
//putchar(tempBuffer[i]);
}
free(buffer);
buffer = tempBuffer;
size *= 10;
}
buffer[count] = getchar();
if(buffer[count] == '\n'){
break;
}
if(buffer[count] == EOF){
buffer[count] = '\0';
break;
}
count++;
}
*bufferPointer = buffer;
*sizePointer = size;
return count-1;
}
int main(){
char * buffer;
char * strings[1000];
int arrayCount =0;
int size = 10;
while(!feof(stdin))
{
buffer= (char*) malloc(size);
getAline(&buffer, &size);
strings[arrayCount++] = buffer;
}
for(int i = 0; i >= 0; i--) {
if(strings[i] == '\0'){
break;
}
printf("%s", strings[i]);
}
return 0;
}

When you reverse a loop's iteration direction, you also have to reverse the beginning and ending values.
for(int i = arrayCount-1; i >= 0; i--)
Now, this loop starts at the end, then works back down to the beginning of the array.

Make int i equal the number of lines in the Constitution instead of 0 that should do it.

Related

Get length of char array with null elements in C

Currently I am making a project that uses char arrays that have null elements. I want to be able to get the length of the array, in the sense of the number of elements that aren't null. This seemed reasonably trivial and I made this function:
int getWordLen(char word[]) {
int count = 0;
for (int i = 0; i < 512; i++) {
if (word[i] != '\0') {
count++;
}
}
printf("%d ", count);
return count;
}
However, every char array returns a length of 188. Any help would be appreciated.
This is the function I was calling it from:
void redact(Words * redactWords, char fileName[]) {
FILE * file = fopen(fileName, "r");
FILE * outputFile = fopen("outputFile.txt", "w+");
char word[512];
int i = 0;
char c;
while (c != EOF) {
c = getc(file);
if ((c > 96) && (c < 123)) {
word[i] = c;
i++;
continue;
}
else if ((c > 64) && (c < 91)) {
word[i] = c + 32;
i++;
continue;
}
i = 0;
if (isWordRedactWord(redactWords, word)) {
//write stars to file
char starStr[512];
for (int i = 0; i < getWordLen(word); i++) {
starStr[i] = '*';
}
fputs(starStr, outputFile);
}
else {
//write word to file
fputs(word, outputFile);
}
strcpy(word, emptyWord(word));
}
fclose(file);
fclose(outputFile);
}
In the initial while, I would only use while(!EOF).
Also, I believe you are using a lot more resources than necessary with the implementation of that for inside the while:
char starStr[512];
for (int i = 0; i < getWordLen(word); i++) {
starStr[i] = '*';
I suggest you to put it outside the while loop and see what happens.
If it is always giving you 188 of lenght, it is counting something that's constant, and may be related to that outer loop.
Hope you can solve it!

How to get words out of a string and put them in an string array ? In C

I basically have a sentence in a string and want to break it down word per word. Every word should go into an array of strings. I am not allowed to use strtok. I have this code but it doesn't work. Can someone help?
There is for sure something similar in the internet but I couldn't find anything...
int main(){
char s[10000]; // sentence
char array[100][100]; // array where I put every word
printf("Insert sentence: "); // receive the sentence
gets(s);
int i = 0;
int j = 0;
for(j = 0; s[j] != '\0'; j++){ // loop until I reach the end
for(i = 0; s[i] != ' '; i++){ // loop until the word is over
array[j][i] = s[i]; // put every char in the array
}
}
return 0;
}
Every word should go into an array of strings. I am not allowed to use
strtok.
Interesting problem which could be resolved in a compact algorithm.
It handles multiple spaces and punctuation marks specified in check(char c).
The most difficult part of the problem is to properly handle corner cases. We may have situation when words are longer more than WORD_LEN length or the number of words exceeds the capacity of the array.
Both cases are properly handled. The algorithm truncates the excessive words and parses only to the capacity of the array.
(BTW. Do not use gets: Why is the gets function so dangerous that it should not be used?)
Edit: The fully tested find_tokens function has been presented.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORD_LEN 3 // 100 // MAX WORD LEN
#define NR_OF_WORDS 3 // 100 // MAX NUMBER OF WORDS
#define INPUT_SIZE 10000
int is_delimiter(const char * delimiters, char c) // check for a delimiter
{
char *p = strchr (delimiters, c); // if not NULL c is separator
if (p) return 1; // delimeter
else return 0; // not a delimeter
}
int skip(int *i, char *str, int skip_delimiters, const char *delimiters)
{
while(1){
if(skip_delimiters) {
if( (str[(*i)+1] =='\0') || (!is_delimiter(delimiters, str[(*i)+1])) )
break; // break on nondelimeter or '\0'
else (*i)++; // advance to next character
}
else{ // skip excess characters in the token
if( is_delimiter(delimiters, str[(*i)]) )
{
if( (str[(*i)+1] =='\0') || !is_delimiter(delimiters, str[(*i)+1]) )
break; // break on non delimiter or '\0'
else (*i)++; // skip delimiters
}
else (*i)++; // skip non delimiters
}
}
if ( str[(*i)+1] =='\0') return 0;
else return 1;
}
int find_tokens(int max_tokens, int token_len, char *str, char array[][token_len+1], const char *delimiters, int *nr_of_tokens)
{
int i = 0;
int j = 0;
int l = 0;
*nr_of_tokens = 0;
int status = 0; // all OK!
int skip_leading_delimiters = 1;
int token = 0;
int more;
for(i = 0; str[i] != '\0'; i++){ // loop until I reach the end
// skip leading delimiters
if( skip_leading_delimiters )
{
if( is_delimiter( delimiters, str[i]) ) continue;
skip_leading_delimiters = 0;
}
if( !is_delimiter(delimiters,str[i]) && (j < token_len) )
{
array[l][j] = str[i]; // put char in the array
//printf("%c!\n", array[l][j] );
j++;
array[l][j] = 0;
token = 1;
}
else
{
//printf("%c?\n", str[i] );
array[l][j] = '\0'; // token terminations
if (j < token_len) {
more = skip(&i, str, 1, delimiters); // skip delimiters
}
else{
more = skip(&i, str, 0, delimiters); // skip excess of the characters in token
status = status | 0x01; // token has been truncated
}
j = 0;
//printf("more %d\n",more);
if(token){
if (more) l++;
}
if(l >= max_tokens){
status = status | 0x02; // more tokens than expected
break;
}
}
}
if(l>=max_tokens)
*nr_of_tokens = max_tokens;
else{
if(l<=0 && token)
*nr_of_tokens = 1;
else
{
if(token)
*nr_of_tokens = l+1;
else
*nr_of_tokens = l;
}
}
return status;
}
int main(void){
char input[INPUT_SIZE+1]; // sentence
char array[NR_OF_WORDS][WORD_LEN+1]; // array where I put every word, remeber to include null terminator!!!
int number_of_words;
const char * delimiters = " .,;:\t"; // word delimiters
char *p;
printf("Insert sentence: "); // receive the sentence
fgets(input, INPUT_SIZE, stdin);
if ( (p = strchr(input, '\n')) != NULL) *p = '\0'; // remove '\n'
int ret = find_tokens(NR_OF_WORDS, WORD_LEN, input, array, delimiters, &number_of_words);
printf("tokens= %d ret= %d\n", number_of_words, ret);
for (int i=0; i < number_of_words; i++)
printf("%d: %s\n", i, array[i]);
printf("End\n");
return 0;
}
Test:
Insert sentence: ..........1234567,,,,,,abcdefgh....123::::::::::::
tokens= 3 ret= 1
0: 123
1: abc
2: 123
End
You are not '\0'-terminating the strings and you are scanning the source from
the beginning every time you've found a empty character.
You only need one loop and, the inner loop and the condition must be s[i] != 0:
int j = 0; // index for array
int k = 0; // index for array[j]
for(i = 0; s[i] != '\0'; ++i)
{
if(k == 99)
{
// word longer than array[j] can hold, aborting
array[j][99] = 0; // 0-terminating string
break;
}
if(j == 99)
{
// more words than array can hold, aborting
break;
}
if(s[i] == ' ')
{
array[j][k] = 0; // 0-terminating string
j++; // for the next entry in array
k = 0;
} else
array[j][k++] = s[i];
}
Note that this algorithm doesn't handle multiple spaces and punctuation marks.
This can be solved by using a variable that stores the last state.
int j = 0; // index for array
int k = 0; // index for array[j]
int sep_state = 0; // 0 normal mode, 1 separation mode
for(i = 0; s[i] != '\0'; ++i)
{
if(k == 99)
{
// word longer than array[j] can hold, aborting
array[j][99] = 0; // 0-terminating string
break;
}
if(j == 99)
{
// more words than array can hold, aborting
break;
}
// check for usual word separators
if(s[i] == ' ' || s[i] == '.' || s[i] == ',' || s[i] == ';' || s[i] == ':')
{
if(sep_state == 1)
continue; // skip multiple separators
array[j][k] = 0; // 0-terminating string
j++; // for the next entry in array
k = 0;
sep_state = 1; // enter separation mode
} else {
array[j][k++] = s[i];
sep_state = 0; // leave separation mode
}
}
As you can see, using the sep_state variable I'm able to check if multiple
separators come one after the other and skips subsequent separators. I also
check for common punctuation marks.
#include <stdio.h>
int main()
{
char s[10000]; // sentence
char array[100][100]; // array where i put every word
printf("Insert sentence: "); // receive the sentece
gets(s);
printf("%s",s);
int i = 0;
int j = 0;
int k = 0;
for(j = 0; s[j] != '\0'; j++){ // loop until i reach the end
if ( s[j] != ' ' || s[j] == '\0' )
{
array[i][k] = s[j];
k++;
}
else {
i++;
k = 0;
}
}
return 0;
}
please note that the gets function is very unsafe and shouldn't in any case be used, use scanf or fgets instead

Numbers in char array printing as random characters

So I'm writing a somewhat simple C program that is supposed to take a string of characters separated by semicolons as input. The program is then supposed to sort the strings by length and print them to the console.
Ex: abc;12;def;1234
The issue I'm having is that any numbers that are entered end up being printed as random symbols and I'm not sure why. I'm taking in input in this function:
void get_strings(char** c)
{
while (scanf("%[^;]s", c[numStrings]) != EOF)
{
getchar();
numStrings += 1;
}
}
Since scanf is looking for strings, if numbers are entered, are they stored as the 'character form' of those numbers, or should I be casting somehow?
Here's the rest of the code:
int numStrings = 0;
void sort_strings(char** c)
{
for (int i = 0; i < numStrings; i++)
{
for (int j = 0; j < numStrings - i; j++)
{
if (strlen(c[j]) > strlen(c[j + 1]))
{
char temp[1000];
strcpy(c[j], temp);
strcpy(c[j + 1], c[j]);
strcpy(temp, c[j + 1]);
}
}
}
}
void show_strings(char** c)
{
for (int i = 0; i < numStrings; i++)
{
if (printf("%s\n", c[i]) != EOF) break;
}
}
int main()
{
char wordLen[100][1000];
char* word2[100];
for (int i = 0; i < 100; i++)
{
word2[i] = wordLen[i];
}
char** words = word2;
get_strings(words);
sort_strings(words);
show_strings(words);
return 0;
}
The parsing code is incorrect:
void get_strings(char **c) {
while (scanf("%[^;]s", c[numStrings]) != EOF) {
getchar();
numStrings += 1;
}
}
the scanf() format contains an extra s that does not match the input.
the return value of scanf() should be compared to 1 to ensure successful conversion. Conversion failure produces EOF only at end of file, otherwise it produces 0 and the contents of c[numStrings] will be indeterminate.
conversion stops at the first character ;, this character stays in the input stream, but it is read by getchar(), yet if there is an empty field, the corresponding conversion would fail and the contents of the array would be indeterminate.
you should not use a global variable for the number of strings read. You should instead return this number.
The sorting code is incorrect too:
the inner loop runs one index too far: j + 1 must be less than numStrings for all runs.
the arguments to strcpy are passed in the wrong order.
strcpy should not be used at all, you should just swap the pointers.
show_strings() always stops after the first line as printf will return the number of characters printed.
You can fix the reading loop this way:
#include <stdio.h>
#include <string.h>
int get_strings(char **c, int maxStrings) {
int numStrings = 0;
while (numStrings < maxStrings) {
switch (scanf("%999[^;]", c[numStrings])) {
case 1:
getchar();
numStrings += 1;
break;
case 0:
if (getchar() == ';') {
c[numStrings] = '\0';
numStrings += 1;
}
break;
case EOF:
return numStrings;
}
}
}
void sort_strings(char **c, int count) {
for (int i = 0; i < count; i++) {
for (int j = 0; j < count - i - 1; j++) {
if (strlen(c[j]) > strlen(c[j + 1])) {
char *temp = c[j];
c[j] = c[j + 1];
c[j + 1] = temp;
}
}
}
}
void show_strings(char **c, int count) {
for (int i = 0; i < count; i++) {
printf("%s\n", c[i]);
}
}
int main(void) {
char words[1000][100];
char *wordPtrs[100];
int numStrings;
for (int i = 0; i < 100; i++) {
wordPtrs[i] = words[i];
}
numStrings = get_strings(wordPtrs, 100);
sort_strings(wordPtrs, numStrings);
show_strings(wordPtrs, numStrings);
return 0;
}

look and say sequence program not outputting correct sequence

This program is taking input from a file named "input.txt" however it is not outputting the correct look and say sequence. The program should input 21 and 114421. The output should be 1211 and 21241211, however it is just giving me nonsense numbers.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
char input[1024]; //The input element
char result[1024]; //The next element
int length = 0; //The length of the input
int resultLength = 0; //The length of the result
FILE *openFile;
openFile = fopen("input.txt", "r");
do{
fgets(input, 1024, openFile);
} while((input[length++] != '.') && (!feof(openFile)));
length -= 1; //Decrement length because of the length++ that just executed
//Go through the loop, adding to the result each time the chain stops
fclose(openFile);
char prev = input[0]; //The previous character
int count = 1; //The count in the current chain
int i, j = 0;
for(i=1; i < length; i++){
if(input[i] == prev){
count++; //If the chain is unbroken, increment the count
} else{
//If the chain breaks, store the count and digit in result and reset count
result[j++] = count + '0';
result[j++] = prev;
count = 1;
}
//Set prev to be the current digit
prev = input[i];
}
//Handle the last digit using the current value of count and prev
result[j++] = count + '0';
result[j++] = prev;
//Print out the result
printf("The next element in the sequence is: ");
resultLength = j;
for(i=0; i < resultLength; i++){
printf("%c", result[i]);
}
printf("\n");
system("pause");
return 0;
}
fix like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
char input[1024];
char result[2*sizeof(input)];
int length = 0;// The length of the input
FILE *openFile = fopen("input.txt", "r");
if(!openFile){
perror("fopen:");
exit(EXIT_FAILURE);
}
while(fgets(input, 1024, openFile)){
char *p = strchr(input, '\n');
if(!p){
fprintf(stderr, "Input too long!\n");
exit(EXIT_FAILURE);
}
*p = 0;//chomp newline
length = p - input;
if(*input == '.' && !input[1]){
puts("c u!");
return 0;
}
//conversion
int resultLength = 0;
int i, j;
for(i = 0; i < length; i = j){
int count = 1;
for(j = i + 1; input[i] == input[j]; ++j)
++count;//Count of repeated characters
while(count > 9){//Processing when the count exceeds 9 E.g 111111111111 ==> 9131
result[resultLength++] = '9';
result[resultLength++] = input[i];
count -= 9;
}
result[resultLength++] = count + '0';
result[resultLength++] = input[i];
}
result[resultLength] = 0;//Add NUL charancter to last for %s of printf
//Print out the result
printf("The next element in the sequence is: %s\n", result);
}
fclose(openFile);
return 0;
}

Messing with Character Arrays in C

Can someone advise why the loop in the main dies after the fifth iteration never completing
it's intended goal of reducing the character array down to 1 final element? I've gotten it this
far and am completely consumed as their should be 11 iterations as returned by the call
size_t strlen( char const *str )
{
int length = 0;
while (*str++ !='\0')
{
length += 1;
}
return length;
}
void abracadabra( char *word )
{
int i, c;
int len = strlen(word)-1;
for (i = 0; i <= len; i++)
{
putchar(*word);
putchar(' ');
*(word++);
}
}
int main()
{
char word[250];
int i, j;
printf ("enter your word:\n");
scanf ("%[^\n]s", &word);
for (i = 0; i <= strlen(word)-1; i++)
{
abracadabra(word);
putchar('\0');
printf("\n");
for (j = 0; j <= i; j++)
{
putchar('\0');
}
word[strlen(word) - 1] = '\0';
}
word[strlen(word)-1] = '\0';
printf("\n");
system("pause");
return 0;
}
Each time you execute the outer for loop in main the size of the string decreases by 1. The counter i is also increasing by 1 each time. This causes you to run the loop half of the times that you intend to.
int size = strlen(word);
for (i = 0; i < size; i++) {
\\same inner code
}
Subbing the above code for the outer for loop in main resolves the issue.
The is mistake in using the variable i and strlen in for loop. i is keep increasing and word length is decreasing. So in the mid, loop is terminated due to i>strlen (word)
int main()
{
char word[250];
int i, j;
printf ("enter your word:\n");
scanf ("%[^\n]s", &word);
// for (i = 0; i <= strlen(word)-1; i++)
while ( strlen(word) )
{
abracadabra(word);
putchar('\0');
printf("\n");
word[strlen(word) - 1] = '\0';
}
word[strlen(word)-1] = '\0';
printf("\n");
system("pause");
return 0;
}

Resources