Nord
Nord

Reputation: 7

Reading a string with fgets into a char array from a filestream. [C]

I am trying to make a programm which decrypts a series of letters from a file. Sadly, I am failing to read the letters into a char array (string) because I do not really know how the fgets() function works. So my actual code looks like this:

#define stringlength 80

int main(void) 
{
   FILE *source;
   char puffer[stringlength], name[20];

   printf("Which file do you want to read: ");
   scanf("%s",name);
   if( (source=fopen(name,"r")) == NULL) 
   {
      fprintf(stderr, "Can not open %s\n", name);
      return EXIT_FAILURE;
   }
   while(fgets(puffer, stringlength, source))
   {
     fputs(puffer, stdout);
   }
   return EXIT_SUCCESS;
}

So actually this kinda works. It opens the command prompt and writes the the sequence of letters in that window. But now I have to use every single letter and compare it with the key's letters. It just compares the right four bits with a XOR to keep the result letter in the same column of the ASCII chart. I have already written a algorithm which works for single letters:

saveLeftFourBits = letterOfFile >> 4;
saveLeftFourBits = saveLeftFourBits << 4;
letterOfFile = letterOfFile & 0x0F;
letterOfKey = letterOfKey & 0x0F;
temp = letterOfFile ^ letterOfKey;
temp |= saveLeftFourBits;

temp should be the resulting letter. So now I am struggling with how to read a single letter from the fgets function into a variable (in letterOfFile) and compare it with the letterOfKey. Or is there maybe a string-function which does that is a lot easier way? I hope someone can help me. :)

Upvotes: 0

Views: 566

Answers (2)

D&#233;j&#224; vu
D&#233;j&#224; vu

Reputation: 28840

puffer is where fgets store a line of 80 chars max, including (if size permits) the trailing \n.

To deal with all characters of a line, do a loop from the start of puffer until you reach the end of line, meaning either \0 or \n

char letterOfKey = '#';     // Define it
char *s;
for(s=puffer ; *s && *s != '\n' ; s++) {
   *s = (*s & 0xF0) | ((*s ^ letterOfKey) & 0x0F); 
}
fputs(puffer, stdout);

Explanation

s points to the beginning of puffer and is incremented. The loop ends when the character pointed to by s is either 0 or \n. For each character in the line, *s, bitwise operations are done and stored back to *s. And,

  • (*s & 0xF0) keeps the 4 MSb
  • | is the bitwise OR
  • (*s ^ letterOfKey) does an Exclusive OR between the 2 operands
  • & 0x0F keeps the 4 LSb

See also Bitwise operations in C

Upvotes: 1

Malcolm McLean
Malcolm McLean

Reputation: 6404

The program is fine. However the shifting and masking looks suspicious to me. I think you've fallen for the common confusion between binary and hex. Binary numbers are the format in which integers are represented natively, and the bitwise operators only make sense on them. Hex number are ASCII strings of characters like "F2E0", the first character is "F", as in "Fred" and needs to be treated as text. You can write a little function to take a character and return an number 0-15, or -1 on error (passed a letter like "K" which doesn't have a hex value").

So like this

int hextobinary(char hex)
{
    /* logic here */
}

int hexstringtobinary(char *hexstr)
{
   int i;
   int answer = 0;
   for(i=0;hextr[i] != '\0';i+++)
   {
      answer *= 16;
      answer += hextobinary(hexstr[i]);
   }
   return answer;
}

As an exercise, put in the error handling if passed a string with non-hex characters in it.

Upvotes: 0

Related Questions