Skip to content

Latest commit

 

History

History
718 lines (545 loc) · 17.5 KB

syntax_testing.org

File metadata and controls

718 lines (545 loc) · 17.5 KB

Started on [2021-07-03 Sat]

I need three functions and some syntax I don’t know yet, let’s do some file IO

Starting

printf ("Hello World!!\n");
#include <stdio.h>
#include <stdlib.h>



int main()
{
   char ch, file_name[25];
   FILE *fp;

   FileIn = fopen("FoxDog.txt", "r");

   if (FileIn == NULL)
   {
      perror("Error while opening the file.\n");
      exit(EXIT_FAILURE);
   }

   printf("The contents of %s file are:\n", file_name);

   while((ch = fgetc(FileIn)) != EOF)
      printf("%c", ch);

   fclose(FileIn);
   return 0;
}

Oh… it’s just one line. Okay. Well that simplifies things a bit. I just need a single vector that has the string split by white space.

https://overiq.com/c-programming-101/array-of-strings-in-c/

Oh joy, it appears to make a vector, I need to define the maximum length first. That means I either hard code the length and manually think of how long it need to be, or I need a function that can look at the file and determine the maximum length I am going to need to before I initialize the vector.

I can imagine a for loop going through all the white space delineated words and simply updating a function local variable with the highest number. But feels like if I am going to find all these words once, I might as well be adding them to a vector.

1 char ch_arr[3][10] = { 2 {’s’, ‘p’, ‘i’, ‘k’, ‘e’, ‘\0’}, 3 {‘t’, ‘o’, ‘m’,’\0’}, 4 {‘j’, ‘e’, ‘r’, ‘r’, ‘y’,’\0’} 5 };

It is important to end each 1-D thing by the null character, otherwise, it will be just an thing of characters. We can’t use them as strings.

Declaring an thing of strings this way is rather tedious, that’s why C provides an alternative syntax to achieve the same thing. This above initialization is equivalent to:

1 char ch_arr[3][10] = { 2 “spike”, 3 “tom”, 4 “jerry” 5 };

https://www.programiz.com/c-programming/c-arrays Not quite what I was looking for but some of the syntax I need is here

…you know what, I will make that a question to ask later. Let’s just eye ball it for now.

char ch_arr[3][5] = {
  {'B', 'o', 'b','\0'},
  {'A', 'n', 'n','\0'},
  {'B', 'e', 'n','\0'},
 }; 
for (int i = 0; i < 3; i += 1){
  printf (ch_arr[i]);
  printf (" ");
  }; 

It’s kind of hacky to get the spaces in there, but it works. Anyway, that is how I will be getting the words FileOut of a vector to write into a file.

Look like

Step two

Looks like I have the basic pieces assembled. I still need writing to a file but that should be a simple search to get the syntax. What I want to try first is get as far as pulling the text from the file, putting it in a vector, and printing reversed strings to the console.

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


int main()
{
  FILE *fp;
  long lSize;
  char *buffer;

  FileIn = fopen ( "FoxDog.txt" , "r" );
  if( !FileIn ) perror("FoxDog.txt"),exit(1);

  fseek( FileIn , 0L , SEEK_END);
  lSize = ftell( FileIn );
  rewind( FileIn );

  buffer = calloc( 1, lSize+1 );
  if( !buffer ) fclose(FileIn),fputs("memory alloc fails",stderr),exit(1);

  if( 1!=fread( buffer , lSize, 1 , FileIn) )
    fclose(FileIn),free(buffer),fputs("entire read fails",stderr),exit(1);

/* do your work here, buffer is a string contains the whole text */
   const char delim[2] = " ";
   char *element = strtok(buffer, delim);
   char *normalWords[10];
   int i = 0; 
      
   while( element != NULL ) {
     normalWords[i++] = element;
     element = strtok(NULL, delim);
   }
/* At this point, all the words of the file are in normalWords. Need to write reversed versions to the file I am about to defie below */

   char result[9][20];
   for(int i = 0; i < 9; i++){
     int j = 0;
     int k = 0;
     int theIndex = 0;
     while (normalWords[i][k] != '\0'){
       j++;
       k++;
     };
     /* hacky way of getting the legnth of this element into j */
     k = 0;
     
     while (normalWords[i][k] != '\0'){
       theIndex = (j - k) -1;
       result[i][k] = normalWords[i][theIndex];
       k++;
     };
     result[i][k] = '\0';
   };
/* wish this could have been cleaner */
   
   FILE *out;
   FileOut = fopen("Reversed.txt", "w");
  
   if(FileOut == NULL) {
     printf("file can't be opened\n");
     exit(1);
   }

for(int m = 0; m < 9; m++){
  fprintf(FileOut,"%s",result[m]);
  fprintf(FileOut," ");
  }
   
   fclose(FileOut);
   fclose(FileIn);
   free(buffer);

   return 0;
}

So close. I not have the whole thing done, I just don’t have a way to reverse each element.

…I could write a function for it?

Keeping an old version

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


int main()
{
  FILE *fp;
  long lSize;
  char *buffer;

  fp = fopen ( "FoxDog.txt" , "r" );
  if( !fp ) perror("FoxDog.txt"),exit(1);

  fseek( fp , 0L , SEEK_END);
  lSize = ftell( fp );
  rewind( fp );

  buffer = calloc( 1, lSize+1 );
  if( !buffer ) fclose(fp),fputs("memory alloc fails",stderr),exit(1);

  if( 1!=fread( buffer , lSize, 1 , fp) )
    fclose(fp),free(buffer),fputs("entire read fails",stderr),exit(1);

/* do your work here, buffer is a string contains the whole text */
   const char delim[2] = " ";
   char *element = strtok(buffer, delim);
   char *normalWords[10];
   int i = 0; 
      
   while( element != NULL ) {
     normalWords[i++] = element;
     element = strtok(NULL, delim);
   }
/* At this point, all the words of the file are in normalWords. Need to write reversed versions to the file I am about to defie below */

   char result[9][20];
   for(int i = 0; i < 9; i++){
     int j = 0;
     int k = 0;
     int theIndex = 0;
     while (normalWords[i][k] != '\0'){
       j++;
       k++;
     };
     /* hacky way of getting the legnth of this element into j */
     k = 0;
     
     while (normalWords[i][k] != '\0'){
       theIndex = (j - k) -1;
       result[i][k] = normalWords[i][theIndex];
       k++;
     };
     result[i][k] = '\0';
   };
/* wish this could have been cleaner */
   
   FILE *out;
   out = fopen("Reversed.txt", "w");
  
   if(out == NULL) {
     printf("file can't be opened\n");
     exit(1);
   }

for(int m = 0; m < 9; m++){
  fprintf(out,"%s",result[m]);
  fprintf(out," ");
  }
   
   fclose(out);
   fclose(fp);
   free(buffer);

   return 0;
}
#include <string.h>

char* reverseMe(char c[]){
  char* result[3];
  int length = sizeof(c)/sizeof(c[0]);
  for (int i = 0; i < length; i++){
    int target = length - i;
    result[target] = c[i];
  } 
  return result;
}


int main(){
  char myString[] = "yo";
  printf(reverseMe(myString));
  return 0;
}

step 2.5

Okay, I just need to get this array revsered… er get a funcitn that can go through an array of strings and reverse all of them. Let’s break that FileOut into it’s own block

/* char reverseIt(char c[3][10]){ */
  /* char result[3][10]; */
  /*   for(int i = 0; i < 3; i++){ */
  /*     int j = 0;   */
  /*     int k = 0; */
  /*     int theIndex = 0; */
  /*     while (c[i][k] != '\0'){ */
  /*       j++; */
  /*       k++; */
  /*     } */
  /*    /\* hacky way of getting the legnth of this element into j *\/ */
  /*    k = 0; */
             
  /*    while (c[i][k] != '\0'){ */
  /*      theIndex = (j - k) -1; */
  /*      result[i][k] = c[i][theIndex]; */
  /*        k++; */
  /*        } */
  /*    result[i][k] = '\0'; */
  /*   } */
  /*    return result; */
/* } */
char myArray[3][10] = {  
  {'s', 'p', 'i', 'k', 'e', '\0'},  
  {'t', 'o', 'm','\0'},  
  {'j', 'e', 'r', 'r', 'y','\0'}  
};

char result[3][10];
for(int i = 0; i < 3; i++){
  int j = 0;  
  int k = 0;
  int theIndex = 0;
  while (myArray[i][k] != '\0'){
    j++;
    k++;
  };
  /* hacky way of getting the legnth of this element into j */
  k = 0;
  
  while (myArray[i][k] != '\0'){
    theIndex = (j - k) -1;
    result[i][k] = myArray[i][theIndex];
    k++;
  };
  result[i][k] = '\0';
 };

printf(result[1]);

wow it worked.

Homework round 2

Task list

  • [X] 1)

Change the main function to the following:

  • [ ] 2)

A. Use an argument for the name of the input file The current exe would be run as “./final” New exe would be run as “./final FoxDog.txt”

B. Use an argument for the name of the output file New exe would be run as “./final FoxDog.txt TestReverse.txt”

  • [ ] 3)

A. Use a double pointer to store the words (strings): E.G. char **stringArray B. Do not use fseek SEEK_END to get the file length. C. Do not calloc one large buffer to read the whole file. D. Use a malloc per each word E. Do the word reversing in a function call.

  • [ ] 4)

Create a new function called ReverseTextNoBuf(FILE*,FILE*) Have this function perform the original task with only a single character buffer no calloc no char *buffer (I did this myself to make sure it was actually possible)

You can just call ReverseTextNoBuf instead of ReverseText (keep the original code). Maybe use a different output file name: “./final FoxDog.txt TextReverseNoBuf.txt”

  • [ ] 5)

Handle the attached file: “./final FoxDog2.txt TextReverseNoBuf.txt”

  • [ ] 6)

Rename “final”, but dont just rename the file, set the output file in the gcc command line when you compile

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


char* revThisString(char *string)
{
  /* To this is my function to reverse a word,
     which I will call once per word in the buffer */
  /* const int* myLength = sizeof(string) / sizeof(string[0]); */

  static char reversed[10];
  /* This hard coded 5 needs to be fixed */

  int j = 0;

  /* Ths 5 below is hard coded and needs to be fixed */
  for(int i = 10; i > -1;)
    {
      reversed[j] = string[i];
      i = i - 1;
      j = j + 1;
    }
  return reversed;
}

int ReverseText(FILE *FileIn, FILE *FileOut)
{
  int lSize;
  char* buffer;

  fseek( FileIn , 0L , SEEK_END);
  lSize = ftell( FileIn);
  rewind( FileIn );
  /* Getting the size of the text I am working with */

  buffer = calloc( 1, lSize+1 );
  if( !buffer ) fclose(FileIn),fputs("memory alloc fails",stderr),exit(1);

  if( 1!=fread( buffer , lSize, 1 , FileIn) )
    fclose(FileIn),free(buffer),fputs("entire read fails",stderr),exit(1);

  /* This makes an array called buffer for holding all the chars */

   const char delim[2] = " ";
   char *element = strtok(buffer, delim);
   char *normalWords[10];
   int i = 0;

   while( element != NULL ) {
     normalWords[i++] = element;
     element = strtok(NULL, delim);
   }
   /* This splits all the "words" into an array called normalWords */
   /*   so they can be reversed by calling reversr on them */

for(int m = 0; m < 9; m++){
  fprintf(FileOut,"%s",revThisString(normalWords[m]));
  fprintf(FileOut," ");
  }
/* writting the words to the file    */

 free(buffer);

  return 0;
}

int main(void)
{

  FILE *in, *out;

  in = fopen("FoxDog.txt" , "r");

  if ( !in ) {

    perror("FoxDog.txt");

    exit(1);

  }

  out = fopen("TextReverse.txt", "w");

  if (out == NULL) {

    fclose(in);

    printf("file can't be opened\n");

    exit(1);

  }

  ReverseText(in, out);

  fclose(out);

  fclose(in);

  return 0;

}

Okay, so

Python feels like cheating now

import os.path


if __name__ == '__main__':
    filename = "FoxDog.txt"
    if not os.path.isfile(filename):
        # testing if the files exists
        print('File does not exist')
    else:
        with open(filename) as f:
            content = f.read()
            word_list = content.split(' ')
            # text is now split by spaces and ready to be written in reverse
            e = open("python_rev_text.txt",'w')
            e.close()
            # blanking the file if it exists first
            ex = open("python_rev_text.txt",'a')
            for word in word_list:
                ex.write(word[::-1])
                ex.write(' ')
            ex.close()
            f.close()

That was such an easy way to do what has been taking me weeks to figure out in C. Once I get this under my fingers it will be nice to have in the tool belt, but to think this is all I have to do in Python is pretty crazy.

Getting closer

Okay, it’s [2021-07-27 Tue] and I have a lot of it working. I just need a way to get the size of the array in the functions right to the words come out in the file correctly.

How about just reading words?

[2021-08-07 Sat] It’s onto week two and I think I need to break the problem down a little more. One of the homework requirements is to read in one word at a time. I realized I don’t know how to do that. Let’s figure it out.

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

int main()
{
   char ch;
   FILE *fp;

   fp = fopen("FoxDog.txt", "r");

   if (fp == NULL)
   {
      perror("Error while opening the file.\n");
      exit(EXIT_FAILURE);
   }

   printf("The contents of the file are:\n");

   while((ch = fgetc(fp)) != EOF)
      printf("%c", ch);

   fclose(fp);
   return 0;
}

okay, so this is a way to get characters out of the file one by one. Ideally, I read in characters into a small buffer one at a time, then write them to the file when I know the word is done.

…but getting characters one at a time sounds like a great way to have data and no where to put it. Don’t I need a memory buffer to put something before I go grabbing it from the file?

Let’s use this and make it read just one word. How do I get it to stop what what is either the end of a word or the end of the file?

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

int main()
{
   char ch;
   FILE *fp;
   char* word;

   fp = fopen("FoxDog.txt", "r");

   if (fp == NULL)
   {
      perror("Error while opening the file.\n");
      exit(EXIT_FAILURE);
   }

   printf("One word in the file is:\n");
   
   for(int i = 0; i < 4;){
     ch = fgetc(fp);
     printf("%c", ch);
     i++;
  }
   
   fclose(fp);
   return 0;
}

Interesting, I can’t tell it to read from another part of the file by just moving “i” because the call to fgetc is not using i to determine where it reads from. hmn. what is Fgetc anyway?

Hmn… I was thinking maybe I could try to read in words at a time by telling a char pointer that the start of the file was a string, but it looks like I can’t treat a file pointer like its a string.

Let’s try a function that just prints the word?

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

void print_next_word(FILE *filePointer, FILE *outPointer){
  char word[10];
  char stopper = 'a';
  int i = 0;
  int length = 0;
  while(stopper != ' ')
    {
      word[i] = fgetc(filePointer);
      stopper = word[i];
      if( feof(filePointer) ) {
        word[i] = ' ';
        i++;
        break;
      }
      i++;
    }
  length = i;
  int j = 0;
  i = i - 1;
  for(j = 0; j < length;)
    {
      fprintf(outPointer,"%c",word[i]);
      j++;
      i = i-1;
      }
}
  
int main( int argc, char *argv[] )
{
  
   char ch;
   FILE *fp;

   fp = fopen(argv[0], "r");
   out = fopen(argv[1],"w"); 
   

   if (fp == NULL)
   {
      perror("Error while opening the file.\n");
      exit(EXIT_FAILURE);
   }

   int breakme = 0;
   while(breakme == 0)
     {
      print_next_word(fp, out);
      if(feof(fp))
        {
        breakme = 1;
        break;
        }
     }
   
   fclose(fp); 
   fclose(out);
   return 0;
}

Okay, I just need to wire up the out file, and I thin this is done.

Okay, psudo-code time

I am REALLY close. That last run has a function that scopes a little 10 size array for holidng a word and prints it to the console each time the functon is aclled (advancing the pointer as it goes. So I just need to the following:

  1. Define a function that takes a file pointer
    1. make a local array
    2. make a counter int
    3. start a while loop
    4. call fgetc on the file pointer
    5. if the chacter at the current indes is a space, break
    6. if fgetc hits the end of the file, break
    7. use the fprintf function to write a word to the file by walking the local array backwards starting at the value the while loop just finished advancing us to
    8. if the end of the file has been reached, return a
  2. Define a main function
    1. Set up a file pointer that looks at the text file
    2. start another while loop
    3. as along as the file pointer hasn’t hit the EOF, keep calling the function to write words to the file one at a time.