Link to home
Start Free TrialLog in
Avatar of thx1138tk421
thx1138tk421Flag for United Kingdom of Great Britain and Northern Ireland

asked on

Unscrambling Hamlet, from file to file

I'm trying to complete the same assignment as listed in this thread:
https://www.experts-exchange.com/questions/21637285/C-programming.html

I'm kind of in the testing stage - this is just partial code.  It compiles just fine, but once I run it, I get an error that windows wants to report to microsoft.  Somehow I don't think they're interested.


char text[35][80];
int x=1;
int y=1;
FILE *scrptr; /* original file */
FILE *unsptr;  /* new file */

int main()
{

/* open file */
if ( ( scrptr = fopen( "scrambled.txt", "r" ) )  == NULL ) {
     printf( "File could not be opened\n" );
}
else {
     /* while not end of file */
     while ( !feof( scrptr ) ) {
          for( x = 1; x = 35; x++ ) {
               for( y = 1; y = 80; y++) {
                    fscanf( scrptr, "%s", text[x][y] );
               }
          }
     }
}


if ( ( unsptr = fopen( "unscrambled.txt", "w" ) )  == NULL ) {
     printf( "File could not be opened\n" );
}
else {
     while ( !feof( stdin ) ) {
          for( x = 1; x = 35; x++ ){
               for( y = 1; y = 80; y++){
                    fprintf( unsptr, "%s", text[x][y] );
               }
          }
     }
}

fclose( scrptr ); /* close scrambled */
fclose( unsptr ); /* close unscrambled */

return 0;

}

I'm sure it's a syntax problem somewhere - every time I sit down to write C I start thinking in other languages.
Avatar of InteractiveMind
InteractiveMind
Flag of United Kingdom of Great Britain and Northern Ireland image

I suspect that your char array is not of the appropriate size for reading the file into it.

Instead, I suggest that you that you read the size of the file, then allocate a buffer -- a char array of only 1D; then read the file into that; like so:


    // Declare variables
    FILE *fIn ;
    FILE *fOut ;
    long file_size ;
    char *buffer ;
   
    // Open stream to input and output files
    fIn  = fopen( "in.txt", "rb" ) ;
    fOut = fopen( "out.txt", "w" ) ;
   
    // Check that there were no errors opening the files
    if ( fIn == NULL || fOut == NULL )
    {
        printf( "\nError opening at least one of the files.\n" ) ;
        return -1 ;
    }
   
    // Get the size of the file
    fseek( fIn, 0, SEEK_END ) ;
    file_size = ftell( fIn ) ;
    rewind( fIn ) ;
   
    // Make sure it has some data in it
    if ( file_size <= 0 )
    {
         printf( "\nThe input file has no data in it. Please give it some content, "+
                 "and try again." ) ;
         return -1 ;
    }
   
    // Allocate enough memory to read the file into
    buffer = (char*) malloc (file_size) ;
    if ( buffer == NULL )
    {
        printf( "\nError allocating memory.\n" ) ;
        return -1 ;
    }
   
    // Read the file into memory
    fread( buffer, 1, file_size, fIn ) ;

Avatar of thx1138tk421

ASKER

That would be great, except for one thing.  We haven't learned how to read the file size, and I don't think he's be too happy to see that in there.

We were given these tips:

You will still pass non-alpha characters
You will shift up 3 letters (not back)
You will still need to wrap the ends of the alphabet
Remember that the computer thinks 'W'=87 (and 'w'=119)
fgets and fputs are your friends
You can assume a maximum length of the input line of 80
Your function should take the 2 strings for an argument

The next to last one caught my eye.
Okay.

Well, reading through your code, I noticed that your for-loops are pretty screwed...

For example, these:

          for( x = 1; x = 35; x++ ){
               for( y = 1; y = 80; y++){
                    fprintf( unsptr, "%s", text[x][y] );
               }
          }
     }

I imagine, should be:

          for( x = 1; x <= 35; x++ ){
               for( y = 1; y <= 80; y++){
                    fprintf( unsptr, "%s", text[x][y] );
               }
          }
     }
good catch.  that would have messed me up for a while.
Or rather:

          for( x = 0; x < 35; x++ ){
               for( y = 0; y < 80; y++){
                    fprintf( unsptr, "%s", text[x][y] );
               }
          }
     }

I'm still getting that error message.   Do you think the array size is what is causing it?  The scrambled text is 35 lines, and the longest of those lines has 50 characters.
What's this line all about:

   while ( !feof( stdin ) ) {
     ..

?

Also, I think you need to swap the x and y components in your access attempts to your array around; so:

   text[x][y]

becomes:

   text[y][x]


> Do you think the array size is what is causing it?
It's possible; see if the above suggestions help first, then we'll look into how the size of the array could effect it...
Rather than reading all the lines into memory, then decoding them all and writing them out,
why don't you read one line at a time, decode it, then write it out.  That way you don't
need to know how many lines are in the file.  Given the behaviour of fgets, you don't even
need to know the length of the longest line.  The code would look something like this:

char linebuffer[1000];
...
whie (fgets(linebuffer, sizeof(linebuffer), fIn) != NULL) {
      // decode the bytes in linebuffer.
      ...
      // write out the line
      fputs(linebuffer, fOut);
}


Alright, i think i've just about got it figured out.  The only thing I can't find is which function I need to use to turn the letters into numbers.  I assume that's how it's done, especially since we were given this hint:

•      Remember that the computer thinks 'W'=87 (and 'w'=119)

I have looked all through the book and through every page of notes, and there's nothing.  How do you convert them to their numerical values and back?  Or am I going at this the wrong way?
char c = 'W' ;

int i = (int ) c ;  // 87

char c2 = (char ) i ;
This is, obviously, wrong:

char linebuffer[2000];
char c[2000];
int i;
char c2[2000];

/* while not end of file */
      while (fgets(linebuffer, sizeof(linebuffer), orgptr) != NULL) {

            c = linebuffer;
            i = (int ) c;
            i = i + 3;
            c2 = (char ) i;
            
            
            
            fputs(c2, newptr);
      }

What do I need to do to make thec arrays take the full contents of linebuffer?
Or maybe the better question is "how do i break the array down into its individual parts and perform the operation on each one?"
I tried running a for loop with arrays[x] where 0<x<2000, but it didn't work so well.  

Another half hour and you'll never have to see this problem again.
ASKER CERTIFIED SOLUTION
Avatar of InteractiveMind
InteractiveMind
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
If you only want to perform the operation on certain characters (i.e. letters only), then in this if statement:

   if ( c[0] != '\n' && c[0] != '\r' )

is where you can filter out any unwanted characters.
The fread/fwrite thing isn't working.  It's giving me all kinds of erros=rs.  What do I need to do to make this part work?

while (fgets(linebuffer, sizeof(linebuffer), orgptr) != NULL) {

          c = linebuffer;
          i = (int ) c;
          i = i + 3;
          c2 = (char ) i;
         
         
         
          fputs(c2, newptr);
}

What errors are you getting? Have you including the correct header?

> What do I need to do to make this part work?
> ..

Well, you see, I recommend you stay away from fgets, for it is deprecated. And if it does encounter a null character in the file, comparing it won't work.. it's prone to errors..
Unfortunately, I don't have the full array of C functions at my disposal.  This is a beginner's class, and the only programming class required for most of us.

I've got it down to just these errors now:
char linebuffer[2000];
char c[2000];
int i;
char c2[2000];

20  c = linebuffer;
21  i = (int ) c;
22  i = i + 3;
23  c2 = (char ) i;

(20) error c2106: '=' left operand must be l-value
(23) warning c4047: '=' : 'char[2000] ' differs in levels of indirection from 'char'
(23) another c2106

Thanks again for your help.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for your help, both of you.  I got it all figured out.  I had to submit it a little late, but better late than not working.  Problem solved.
<high five>

Good luck with the course.
Thanks very much, Netminder. :-)