ok, I have a very serious somewhat simple problem that I just can't seem to figure out myself. Simply put I want to make a program take the lines

Hello
How
Are You
ToDay

and output

ToDay
Are You
How
Hello

Using the End of data marker as a newline character.
The size of the data inbetween newline characters can be any size from 1 000 000 to 5 characters.
So far this is what I got

FILE * in = fopen("input.txt","r");
	
	int newlcount = 0;
	int total = 0;
	char ch;

	for(ch = '\n';ch != EOF;total++)
	{
		ch = fgetc(in);
		if (ch == '\n')
			newlcount++;
	}

	rewind(in);

	total = newlcount;

	FILE*out = fopen("flipped lines.txt","w");

	for(int num = 0,count = 0;num < total;num++)
	{
		while ((total - num) != count)
		{
			ch = fgetc(in);
			if (ch == '\n')
			{
				count++;
			}
		}

		count = 0;
		ch = 'x';

		while (ch != '\n'&&ch!= EOF)
		{
			ch = fgetc(in);
			printf("%c",ch);
		}
		rewind(in);
	}

people might argue that this works, but it doesn't. I would like this program to be solved by any means necessary as long as its in C/C++.

Recommended Answers

All 15 Replies

oh wow, Ironically a few seconds after I watched this when I saw it I realized I needed to ... blah blah blah
Anyway Long story short I figured it out, for those of you who are curious this is the solution.

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>


int main (int argc,char* argv [])
{
	FILE * in = fopen("input.txt","r");

	int num,newlcount,totalch,newlines;
	num = newlcount = totalch = newlines = 0;

	for(char ch = 'x';ch!= EOF;totalch++)
		if((ch = fgetc(in)) == '\n') newlines++;
		
	printf("characters processed : %d\n",--totalch);
	printf("Number of lines procressed : %d\n",newlines);

	rewind(in);
	FILE*out = fopen ("flipped lines.txt","w");

	for(int ch = fgetc(in);newlines!= 0;ch = fgetc(in))
	{
		if(ch == '\n')
			newlcount++;

		if (newlcount == newlines)
		{
			for(ch = 'x';ch != '\n'&&ch!= EOF;)
			{
				ch = fgetc(in);
				if (ch!=EOF)
					fprintf(out,"%c",ch);
			}
			
			if(ch == EOF) 
				fprintf(out,"\n");

			newlines--;
			newlcount = 0;
			rewind(in);
		}
	}
	fclose(in);		
	fclose(out);


	system("pause");
	
}
Member Avatar for dmachop

ok, I have a very serious somewhat simple problem that I just can't seem to figure out myself. Simply put I want to make a program take the lines

Hello
How
Are You
ToDay

and output

ToDay
Are You
How
Hello

Using the End of data marker as a newline character.
The size of the data inbetween newline characters can be any size ................program to be solved by any means necessary as long as its in C/C++.

It seems you're making the problem much complex. Here's the solution to your problem:
1. use fscanf() since in this case you're using only one word per line.
remember, fscanf() gets the string until a whitespace/newline is encountered.so, the whole word gets stored.
2.use a counter to store the value in a 2D array.
3.display the result in the reverse order.

#include<stdio.h>
#include<conio.h>
#include<fstream.h>

int main()
{
	FILE *fp;
	char str[10][10];
	int i=0,j=0;
	fp=fopen("input.txt","r");
	while(!feof(fp))
	{
		fscanf(fp,"%s",str[i]);
		i++;
	}
	fclose(fp);
	printf("\nOutput:\n");
	for(j=i-1;j>=0;j--)
	{
		printf("%s\n",str[j]);
	}
}

I think this would do your problem good.
Any question???

SNIP

dmachop> Any question???
Yes, a couple.

>#include<conio.h>
>#include<fstream.h>
What do you need those for?

>fp=fopen("input.txt","r");
What happens if the file doesn't exist?

>char str[10][10];
What happens if the file contains strings longer than 9 characters long? Or more than 10 strings?

>fscanf(fp,"%s",str);
What happens if fscanf() is not successful reading converting a string? What's dumped into str then?

>int main()
Where's the return of main?

>while(!feof(fp))
feof() is true only when the EOF is read and not when EOF is reached. What happens to the loop then?

Alright. I admit, that's more than a couple questions.

commented: good points. +9
Member Avatar for dmachop

>Aia,
Yes, I admit that there are a lot of loopholes in the program given but it solves the purpose for alphaeis............<conio.h> isn't needed since <stdio.h> includes methods such as printf,scanf,fopen,fclose.


Asking these questions aren't difficult enough.........
Anyway here's the answer.........

for <fstream.h>
http://www.cplusplus.com/reference/iostream/fstream/

and for <conio.h>
it's compiler dependent..............
It's console input and output header file.......which is quite different from <stdio.h> which is a standard header file.

for fopen();
If fopen is unsuccessful, then it returns NULL.
So, we oughta check if it's NULL or not.
if(fp==NULL)
printf("......blah.......");

Then, for the 2D Array, you can use a double pointer..........then size constraint disappears.

Generally, feof() returns non-zero number if end of file is reached...(i'm not sure or the reverse.....).

Oh yeah, I've forgot to return a value which gives me a warning.
The int returned by main() is a way for a program to return a value to "the system" that invokes it. On systems that doesn't provide such a facility the return value is ignored, but that doesn't make "void main()" legal C++ or legal C. Even if your compiler accepts "void main()" avoid it, or risk being considered ignorant by C and C++ programmers.

So, Aia you're "more than a couple" of questions(you seem to know the answer) were answered and I hope it's correct to my knowledge.......
--------------------------------------------------------------------------------
Add to my reputation if I'm correct.

Yes, I admit that there are a lot of loopholes in the program given but it solves the purpose for alphaeis............

But what we like to do here is help them solve their own problems, not hand them a solution. After all, you don't get their grade. Therefore, it doesn't "solve the purpose for alphaeis", which is learning to do for himself.

Asking these questions aren't difficult enough.........
Anyway here's the answer.........

for <fstream.h>
http://www.cplusplus.com/reference/iostream/fstream/

and for <conio.h>
it's compiler dependent..............
It's console input and output header file.......which is quite different from <stdio.h> which is a standard header file.

The questions were not asked to have you prove you know what the statements do, but to ask why you used them if you didn't need them and why you didn't use any obvious error processing.

Then, for the 2D Array, you can use a double pointer..........then size constraint disappears.

No it doesn't. If all you define are double pointers you have no storage space, and a guaranteed problem.

dmachop> Yes, I admit that there are a lot of loopholes in the program given but it solves the purpose for alphaeis
I am afraid I can not find the meaning of alphaeis. But if by loopholes, you mean your code is full of pitfalls, I agree, and some I have pointed out already.

<fstream.h> is not a C standard. And as well as you have said with <conio.h> there are not need in your code.


>If fopen is unsuccessful, then it returns NULL.
The answer to my question is: if the file doesn't exist your code is garbage, since you didn't check for a success.

>Then, for the 2D Array, you can use a double pointer..........then size constraint disappears.
Double pointers do not magically create memory allocation to receive everything you want to dump to it.
The answer to my question is: if the file contains strings larger than 9 characters and more than 10 string, your code is garbage because you didn't limit the reading to 10 strings of 9 char long + '\0'

>Generally, feof() returns non-zero number if end of file is reached...(i'm not sure or the reverse.....).
The answer to my question is: your code is broken because feof() is not suitable as a loop control since it will never stop when it reaches an EOF, but rather when it is read and returned.

>Yes, I admit that there are a lot of loopholes in the program given but it solves the purpose for alphaeis
In conclusion, a broken code doesn't solve any purpose, but rather becomes a disservice to the those learning to program.

I think this code will be a better resolver to your problem

#include<stdio.h>
#include<conio.h>
#include<fstream.h>

int main()
{
	FILE *fp;
	char str[10][10];
	int i=0,j=0;
	fp=fopen("input.txt","r");
	while(!feof(fp))
	{
		fscanf(fp,"%s",str[i]);
		i++;
	}
	fclose(fp);
	printf("\nOutput:\n");
	for(j=i-1;j>=0;j--)
	{
		printf("%s\n",str[j]);
	}
}
commented: phail -3
commented: QUIT USING COMPILER DEPENDENT, NON-STANDARD LIBRARIES +9
commented: phear da bears u feed! -1
commented: With all the crap dmachop got for posting bad code, one would think you would have decided not to post bad code yourself. -4
#include<stdio.h>
main()
{
  int i;
  char s[5][10];
  for(i=0;i<4;i++)
    gets(s[i]);
  for(i=3;i>=0;i--)
    printf("%s\n",s[i]);
}

try this
give that 4 inputs
and see the result

commented: ramyasowbhagya(fail); -3
commented: gets()? GETS()???? how about GTFO with that crap -2
commented: phear da bears u feed! -1
commented: My Ghod, another one!!!! -4

Before anyone else wishing to join this parade of failure code and make a contribution to it, at least should read the rules of how to post code between proper tags.
Who knows, the judges may even give you the first prize. A magnificent F certificate.

commented: Well said. +5

>Who knows, the judges may even give you the first prize. A magnificent F certificate.
Ooh, I want in on that:

#include <stdio.h>
#include <string.h>

int main ( void )
{
    char buf[BUFSIZ];

    if ( fgets ( buf, sizeof buf, stdin ) != NULL ) {
        main();
        buf[strcspn ( buf, "\n" )] = '\0';
        printf ( ">%s<\n", buf );
    }

    return 0;
}
Member Avatar for dmachop

Aia, you know the answer and I don't know it.
So, what do you think is the solution instead of having a sizeable 2D Array???

Atleast you must reveal the answer instead of pinpointing the mistakes of a garbage code.........Even (Mod) doesn't seem to reveal it.

>Who knows, the judges may even give you the first prize. A magnificent F certificate.
Ooh, I want in on that:

I'm in too :) The OP said that this code could be in either C or C++, so I thought I'd make my brainvommit in c++

#include <string>
#include <iostream>
#include <vector>

int main(void)
{
    const int SIZE = 4;
    static bool showing = false;
    static std::vector<std::string> strings;
    if (strings.size() != SIZE && !showing){
        std::string str;
        std::getline(std::cin,str);
        strings.push_back(str);
    }
    else {
        showing = true;
        std::cout << strings.at(strings.size()-1) << "\n";
        strings.pop_back();
        if (strings.empty()) 
            return 0;
    }
    main();
}

Disclaimer:
If you accidentally came by this thread and saw my code posted above: never ever ever use it ;)

[edit]
Come to think of it, I could have thrown a few "goto's" in there, to obfuscate it a bit more

>Aia, you know the answer and I don't know it.
There's no THE answer. It's all about finding the right trade-off for the situation.

>So, what do you think is the solution instead of having a sizeable 2D Array???
The OP came up with a trade-off that swaps memory for time. Instead of having a sizable array and storing the strings in memory all at once, he constantly runs through the file and rewinds. The trade-off is that his solution is a great deal slower than the solutions that use more memory.

A nice compromise is to run through the file once building a list of indices where each index is the result of ftell just after a newline. Then instead of reading the file over and over again, simply seek to the desired index and read a line. This minimizes memory usage while offering the most efficient means of reading lines from the file in an unusual manner.

>The OP said that this code could be in either C or
>C++, so I thought I'd make my brainvommit in c++
Then your code is broken. C++ doesn't allow recursive calls to main. Note that I wasn't trying to post the worst code I could write. The solution is still perfectly viable if you remove the bad practice of calling main recursively (in C, where it's legal):

#include <stdio.h>
#include <string.h>

void rev_lines ( FILE *in )
{
    char buf[BUFSIZ];

    if ( fgets ( buf, sizeof buf, stdin ) != NULL ) {
        rev_lines ( in );
        buf[strcspn ( buf, "\n" )] = '\0';
        printf ( ">%s<\n", buf );
    }
}

int main ( void )
{
    rev_lines ( stdin );
    return 0;
}

Of course recursion introduces other problems, such as the size of the stack and overflow when the number of lines in the file exceeds the size of the frame stack. It also doesn't save memory in any way. If anything, the memory footprint is worse due to the overhead of stack frames on top of the memory used for each line.

For a serious and general solution, I'd prefer a hybrid of the two. For small files, go with either recursion or arrays to keep everything simple, fast, and in memory. For large files, use a list of indices and play seeking games to keep the memory footprint low without the extreme performance overhead that the OP's original solution exhibits:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static int getline ( char *buf, int n, FILE *in )
{
    int len = -1;

    if ( fgets ( buf, n, in ) != NULL ) {
        len = strlen ( buf );
        
        if ( buf[len - 1] == '\n' )
            buf[--len] = '\0';
    }

    return len;
}

static void reverse_lines_small ( FILE *in )
{
    char buf[BUFSIZ];

    if ( getline ( buf, sizeof buf, in ) >= 0 ) {
        reverse_lines_small ( in );
        printf ( ">%s<\n", buf );
    }
}

static void reverse_lines_large ( FILE *in )
{
    struct node {
        fpos_t index;
        struct node *next;
    } *temp, *stack = NULL;

    char buf[BUFSIZ];

    /* 
        Build a stack of indices where each index 
        points to the beginning of a line 
    */
    do {
        temp = malloc ( sizeof *temp );

        if ( temp == NULL )
            break;

        if ( fgetpos ( in, &temp->index ) != 0 ) {
            free ( temp );
            break;
        }

        temp->next = stack;
        stack = temp;
    } while ( getline ( buf, sizeof buf, in ) >= 0 );

    rewind ( in );

    /*
        Pop indices off the stack and read the line
        at that location to get the lines in reverse
    */
    while ( stack != NULL ) {
        temp = stack->next;

        if ( fsetpos ( in, &stack->index ) == 0 &&
             getline ( buf, sizeof buf, in ) >= 0 )
        {
            printf ( ">%s<\n", buf );
        }

        free ( stack );
        stack = temp;
    }
}

int main ( int argc, char *argv[] )
{
    FILE *in = stdin; /* Default to stdin */
    int large = 0;    /* Default to small files */
    int i;

    for ( i = 1; i < argc; i++ ) {
        if ( argv[i][0] == '-' ) {
            if ( strcmp ( argv[i], "-large" ) == 0 )
                large = 1;
        }
        else if ( in == stdin ) {
            in = fopen ( argv[i], "r" );

            if ( in == NULL )
                in = stdin;
        }
    }

    if ( !large )
        reverse_lines_small ( in );
    else
        reverse_lines_large ( in );

    if ( in != stdin )
        fclose ( in );

    return 0;
}

Note that I wasn't trying to post the worst code I could write.

Neither was I.

>The OP said that this code could be in either C or
>C++, so I thought I'd make my brainvommit in c++
Then your code is broken. C++ doesn't allow recursive calls to main.

This is news to me. I found out that:

3.6.1.3
"The function main shall not be used within a program."

5.2.2.9
"Recursive calls are permitted, except to the function named main"

But VS will compile it without warning on warning level 4 and G++ will also compile it with -Wall (no warning shown). That's kinda strange isn't?
(you're probably going to explain in great detail why this isn't strange at all right? :icon_smile: )

>you're probably going to explain in great detail why this isn't strange at all right?
Just to be unpredictable, I might not.

>But VS will compile it without warning on warning level 4
>and G++ will also compile it with -Wall (no warning shown).
>That's kinda strange isn't?
Not really. I can see three immediate reasons why a compiler would neglect to implement that constraint.

  1. Cost vs. Benefit: Given how often main is called recursively in code (that is, not very), I'd say it's hard to justify adding an edge case feature. You can see that in a bunch of edge cases and gray areas. The vendor simply doesn't allocate enough resources to do it 100% because there's no pressing need.

    One huge example (where both CL and GCC are equally guilty) is export . This is a big complex feature that nobody who understands it seems to want. Both GCC and CL probably have significant code issues where export is concerned and the cost for adding it is prohibitive when taking demand into account.

  2. Backward Compatibility: For compilers that existed before C++ was standardized, I have no doubt that they see this constraint as a breaking change. C, of course, supports recursive calls to main, so it's easy to imagine how pre-standard C++ compilers would assume that to remain the case in C++.
  3. Additive Risk: When making any change, there's the risk of introducing bugs. This adds greatly to the cost of the feature, which means there has to be sufficient demand for it to justify the risk.
commented: But your not unpredictable :) +17
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.