C - reading multiple file streams - c

Im writing my own simplified version of the classic UNIX program 'wc' (word count). It counts number of lines, words, and characters. All these features work fine. But where i run into trouble is when im trying to read multiple files from *argv[x]. I need to make every variable into an array, and run the whole process through loops to achieve what im looking for.
My program returns a segmentation fault. Something is not being assigned into the arrays at some point in the code, and i can't seem to figure out exactly where that is.
Any help is much appreciated :)
/*
* [PROGRAM] wc (word count)
* [AUTHOR] Jesper M. Olsen # jm0.codes
* [DATE] September 9th 2015
* [PURPOSE] Returns number of lines, words, and characters in a file
*
* [DESCRIPTION] This program is meant to be utilized as a handy little browsing tool.
* For instance, while moving through the filesystem of a programming archive,
* just type 'wc <filename>' and you will get number of lines, words and characters returned promptly.
*/
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc == 1)
return -1;
int numL[argc]; /* initialize array value placeholders */
int numW[argc];
int numC[argc];
int getC[argc];
int getW[argc];
int setNull;
for (setNull = 1; setNull <= argc-1; setNull++) { /* assign ZERO to value placeholders */
numL[setNull] = 0;
numW[setNull] = 0;
numC[setNull] = 0;
getW[setNull] = 0;
}
int x;
FILE *fOp[argc-1];
for (x = 1; x <= argc-1; x++) { /* open file stream for each file */
fOp[x] = fopen(argv[x], "r");
if (fOp[x] == NULL)
return -1;
}
int y;
for (y = 1; (getC[y] = getc(fOp[y])) != EOF; y++) {
if (getC[y] == '\n') numL[y]++;
if (getC[y] == ' ' || getC[y] == '\n' || getC[y] == '\t') getW[y] = 0;
else if (getW[y] == 0) {
getW[y] = 1;
numW[y]++;
} numC[y]++;
}
int z;
for (z = 1; z <= argc-1; z++) { /* close files */
fclose(fOp[z]);
}
int c;
for (c = 1; c <= argc-1; c++) {
printf("[%s] %dL %dW %dC\n", argv[c], numL[c], numW[c], numC[c]);
}
return 0;
}

This will cause a segfault when you reach the last file
FILE *fOp[argc-1];
for (x = 1; x <= argc-1; x++) { /* open file stream for each file */
fOp[x] = fopen(argv[x], "r");
if (fOp[x] == NULL)
return -1;
}
because the array is not large enough. It should be
FILE *fOp[argc];
The mistake would be easier to see if you used
< argc
instead of
<= argc-1
in your loops.

I think problem may be
here -
for (y = 1; (getC[y] = getc(fOp[y])) != EOF; y++) {
if (getC[y] == '\n') numL[y]++;
if (getC[y] == ' ' || getC[y] == '\n' || getC[y] == '\t') getW[y] = 0;
else if (getW[y] == 0) {
getW[y] = 1;
numW[y]++;
} numC[y]++;
}
As arrays can argc number of elements but with this loop you may have read and stored integers more than argc in getC . Thus getting Seg Fault .
But we don't know what it inside files we can't be sure.
Try increasing size of arrays .
Note - It is better to initialize array starting with index 0. In this code you haven't use index 0.

Related

Finding non-integer in a string

I'm trying to error check command line arguments to make sure they are integers, and surprisingly having a difficult time doing so. Here is a snippet of code I have that works when all the command line arguments are integers.
Program can have infinite values passed into it.
One example: ./program -p 45 67 3 9 1
for (argCounter = 2; argCounter < argc; argCounter++)
{
total = total * atoi(argv[argCounter]);
}
What happens when a user types 5g? atoi() converts it to 5. I need to it to return an error. For some reason I was having trouble getting isdigit() to work properly as well. I tried so many random things that my head is spinning at this point. So what I'm trying to do is:
for (argCounter = 2; argCounter < argc; argCounter++)
{
//pseudocode
if (argv[argCounter] != integer)
{
printf("Error!");
return 0;
}
total = total * atoi(argv[argCounter]);
}
You can use sscanf(). Its %n placeholder can be used to determine the number of characters consumed, which you can compare to the string length:
for (argCounter = 2; argCounter < argc; argCounter++)
{
int value, consumed;
if ((sscanf(argv[argCounter], "%d%n", &value, &consumed) != 1) ||
(argv[argCounter][consumed] != '\0'))
{
printf("Error!");
return 0;
}
total *= value;
}
Or, you can use strtol(). It can output a pointer to the first unparsed character. You can check to see if that character is a null terminator or not:
for (argCounter = 2; argCounter < argc; argCounter++)
{
char *end;
errno = 0;
long value = strtol(argv[argCounter], &end, 10);
if ((end == argv[argCounter]) ||
(*end != '\0') ||
(((value == LONG_MIN) || (value == LONG_MAX)) && (errno == ERANGE)))
{
printf("Error!");
return 0;
}
total *= value;
}
Well I'm quite a beginner and I don't exactly understand what you want to do exactly?
if I understand, you want to check if all arguments are numbers (only digits) included in the integer range you want that total contain the produce of the multiplication of all these integers (and I assume you also want total to be in integer range?)
long long total = 1;
for (argCounter = 1; argCounter < argc; argCounter++)
{
char *check_end;
long long nbr = stroll(arg[argCounter], &check_end, 10);
if (!argv[argCounter][0]|| *check_end || nbr > INT_MAX || nbr < INT_MIN || nbr * total > INT_MAX || nbr * total < INT_MIN)
{
total = 0;
printf("Error\n");
break;
}
total *= nbr;
}
maybe this should help, stroll convert a string (given as first parameter) in a base(given as third parameter) to a long long and set the string's pointer (given as second parameter) to the place on the string where the conversion stopped (\0 if only digits after the sign) you could check the stroll man; anyway im not sure my code is very optimised or functional and you may want to get an int at the end so cast as int total variable to an int variable.

C stack corrupted for a string var

So as a part of a class project, I'm supposed to receive an input string from the user and to varies actions on it. For some reason, I get a stack corrupted error in the following code.
void main()
{
char cmd[80] = "", substr[81] = "", matrixName1[11], matrixName2[11], substrFrob[11] = "";
int start = 0, end = 0, cmdSort, i, j, prog = 0, row = 0, col, row1, row2, col1, col2, **matrix1, **matrix2, trace = 0, words, matrixNum = 0;
memset(matrixName1, 0, strlen(matrixName1)); //reseting variables
memset(matrixName2, 0, strlen(matrixName2));
printf_s("#");
fgets(cmd, sizeof(cmd), stdin);
words = wordCounter(cmd);
start = end;
stringCutter(substr, cmd, &start, &end);
while (1)
{
if (prog == 0) //sorting for command and number of args
{
if (!strcmp(substr, "exit") && words == 1) break;
else if (!strcmp(substr, "zeroes") && words == 4) cmdSort = 1;
else if (!strcmp(substr, "set") && words > 1) cmdSort = 2;
else if (!strcmp(substr, "echo") && words == 2) cmdSort = 3;
else if (!strcmp(substr, "frob") && words == 3) cmdSort = 4;
/* rest of the code*/
if (matrixName1[0] != 0) //freeing memory
{
for (i = 0; i < row1; i++)
free(matrix1[i]);
free(matrix1);
}
if (matrixName2[0] != 0)
{
for (i = 0; i < row2; i++)
free(matrix2[i]);
free(matrix2);
}
//system("cls");
//exit(0);
now as a part of the project we can't use any function within stdlib.h expect malloc and free. once I removed the exit(0), I started to receive an error when the user enters "exit" -
"Run time check Failure #2 stack around the variable 'substr' was corrupted"
but for the life of me, I can't find whats wrong.
thank in advence.
I couldn't check your code but it's likely that you are not allocating enough space for the char arrays. Trying to write to the char array that was not previously allocated can corrupt stack cookies hence the error.
If you had provided the full code I would try running it. In this case I can only guess :)
Edit: You might not be using the strlen right. You should be using "sizeof(char) * charcount " instead on memset calls.

Input in specific format (matrix)

I have an issue with input in my homework. On stdin, I will get a specifically formatted input.
In first line, there will be 2 integers, that determine the size of a matrix (rows and cols). All the lines after represent rows of the matrix.
I essentially want to do something like getline(), but I don't want to use getline(). In fact I can't, its forbidden in the homework. Therefore I have to scan int by int (or char by char I guess). The issue here is I need it to be bulletproof (almost). Dummy-proof at least.
I'm imagining a big while loop that keeps going until EOF and inside that another loop (perhaps?) which always reads a line, saves it to my allocated matrix and carries on to the next. I'm aware that I'm supposed to be checking for '\n', but I kind of lack the ability to think of a solution today.
Here's what I'm working with: My matrices are a structure.
struct Matrix{
int nrows;
int ncols;
int** matrix;
};
I then have multiple functions.
A function to dynamically allocate space for the matrix of specific size:
struct Matrix init_matrix(int r, int c)
{
struct Matrix mat;
mat.nrows = r;
mat.ncols = c;
mat.matrix = calloc(r, sizeof(int *));
for(int i = 0; i < r; ++i)
{
*(mat.matrix+i) = calloc(c, sizeof(int));
}
return mat;
}
A function to free the previously allocated space:
void free_matrix(struct Matrix mat)
{
int top = mat.nrows;
for(int i = 0; i < top; ++i)
{
free(mat.matrix[i]);
}
free(mat.matrix);
}
Those 2 functions work perfectly fine.
Now I'm trying to make a function create_matrix(void) (at least I think it shouldn't take any args), that will read the input I'm supposed to receive, for example:
3 3
1 2 3
4 5 6
7 8 9
when the function reads the input, it could tell if the input is incorrect or is in incorrect format and exit the program with corresponding exit value (like 100 f.e.) If the input is correct and in correct format, it calls init_matrix() and then saves input to the matrix.
For your deeper understanding: the whole input I'm supposed to receive is:
matrix A (like above, size in first line, values in lines after)
an operation (+,-,*)
matrix B
Then execute the operation (A*B, A+B etc.). I'm trying to make most things into functions, so the main would be very simple, f.e.
int main(int argc, char *argv[])
{
struct Matrix mat1 = create_matrix();
char operation = get_operation();
struct Matrix mat2 = create_matrix();
struct Matrix result = compute(mat1,mat2, operation);
return 0;
}
Something in those lines, if you get me. The thing is I want to make the program complex enough so that I could later edit it to handle a bigger sequence (up to 100) of matrices than just two. Right now I could do it the dirty way, make it work for two matrices with one operation, but that's not what I really want.
Well, here's how I solved it. It works. It's not anywhere close to perfect, but it works, upload system took it and gave it full amount of points, so I'm satisfied.
struct Matrix read_matrix(FILE *fp)
{
struct Matrix mat;
//FIRST LINE
int ch;
int i = 0;
int n = 20;
char* line = calloc(n,sizeof(char));
while((ch = fgetc(fp)) != EOF && ch != '\n')
{
*(line + i++) = ch;
}
*(line + n-1) = '\0';
int r,c;
int k = sscanf(line,"%d %d", &r, &c);
if(k != 2)
{
fprintf(stderr, "Error: Chybny vstup!\n");
exit(100);
}
free(line);
//MATRIX
line = calloc(c, sizeof(int));
mat = init_matrix(r, c);
i = 0;
r = 0;
while(r < mat.nrows && (ch = fgetc(fp)))
{
if(ch == '\n' || ch == EOF)
{
*(line + i) = '\0';
int offset;
char *data = line;
for(int j = 0; j < mat.ncols; ++j)
{
int d = sscanf(data, " %d%n", &mat.matrix[r][j], &offset);
if(d != 1){
fprintf(stderr, "Error: Chybny vstup!\n");
exit(100);
}
data += offset;
}
i = 0;
++r;
if(ch == EOF){
break;
}
} else
{
*(line + i++) = ch;
}
}
free(line);
return mat;
}

Taking the crypt of a password is adding some weird foobar thing so that it doesn't equal

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <crypt.h>
int main(int argc, string argv[])
{
if(argc > 2){ printf("too many arguments\n"); return 51; }
if(argc < 2){ printf("too few arguments\n"); return 50; }
//if(strlen(argv[1]) > 4){ printf("Password is greater than 4 characters\n"); return 52; }
if(argc == 2) //make sure there are enough args
{
char hash_guess[] = "rofk";
//long long counter = 0;
//while(guess != argv[1]) //crypt(hash_guess, "50") != argv[1]) //while answer not correct
//{
for(int a = 65; a < 91; a++)
{
for(int b = 65; b < 91; b++)
{
for(int c = 65; c < 91; c++)
{
for(int d = 65; d < 91; d++)
{
for(int A = 0; A < 9; A = A + 5) //control if first is caps or not
{
for(int B = 1 ; B < 9 ; B = B + 5)//control if second is caps or not
{
for(int C = 2; C < 9; C = C + 5) //control if third is caps or not
{
for(int D = 3; D < 9; D = D + 5) //control if fourth is caps or not
{
hash_guess[0] = a;
hash_guess[1] = b;
hash_guess[2] = c;
hash_guess[3] = d;
hash_guess[A] = tolower(hash_guess[A]);
hash_guess[B] = tolower(hash_guess[B]);
hash_guess[C] = tolower(hash_guess[C]);
hash_guess[D] = tolower(hash_guess[D]);
printf("%s\n", hash_guess);
string cryptoguess = (crypt(hash_guess, "50"));
string input = argv[1];
if( cryptoguess == input ) { return 0; }
}
}
}
}
}
}
}
//}
//}
//string guess = crypt(hash_guess, "50");
//printf("%lli", counter);
}
}
}
I'm trying to make a program that goes through every 4 letter word, starting on aaaa and going to ZZZZ. I got that part done.
Part of the assignment is to encrypt that, and if the encryption matches an encrypted password, then you know you "hacked" their password. When I compare the encrypted password that I manually enter and the one that comes up by using the crypt function, they are the same, but in the debugger I see this for when it is encrypted by the computer:
"0x7ffff7dd9200 <_ufc_foobar+131200> "50k72iioeOiJU""
and the normal one that I enter shows
"0x7fffffffe34f "50k72iioeOiJU""
the same thing without the _ufc_foobar. Does anyone know why that is there and how I can get rid of it?
The weird junk you are seeing is visualization of offsets of memory addresses in your code which can be ignored.
In your code you are using string when GNU specifies char * is the result of the crypt function.
Therefore, you cannot compare the pointers to the char array using == but instead need to use strcmp C comparing pointers (with chars)
For crypt see: http://www.gnu.org/software/libc/manual/html_node/crypt.html
<_ufc_foobar+131200> isn't part of the string. It's your debugger attempting to figure out where the string came from, and assign a name to it. In this case, it's come up with a bogus result -- _ufc_foobar is the name of a function or variable somewhere else in the program, and your string happens to be stored 131,200 bytes (about 128 KB) after that in memory.
You can safely ignore this. Your strings are equal. They just happen to be stored in different parts of memory (which is normal).

Stack around the variable 'ch' was corrupted

I am in the process of writing a decipher algorithm for Vegenere Variant Cipher and ran into some C specific issues(I am not too familiar with C).
I get
"Run-Time Check Failure #2 - Stack around the variable 'ch' was corrupted" error.
If I understand the error right, ch is not available when I try to read/write to it(ch in this case represents a HEX value read from the text file, I have posted the code of the function below).
But, for the life of me, I can't figure out where it happens. I close the file way before the I exit the function(exception is thrown at the time I leave the function).
Can you take a look an let me know where I have it wrong? Thanks in advance.
P.S. I am tagging the question with C++ as well as it should pretty much be the same except, maybe, how we read the file in.
Anyways, my code below:
int getKeyLength(char *cipherTxtF){
int potKeyL = 1;
float maxFreq = 0.00;
int winKL = 1;
for (potKeyL = 1; potKeyL <= 13; potKeyL++)// loop that is going through each key size startig at 1 and ending at 13
{
unsigned char ch;
FILE *cipherTxtFi;
cipherTxtFi = fopen(cipherTxtF, "r");
int fileCharCount = 0;
int freqCounter[256] = { 0 };
int nThCharCount = 0;
while (fscanf(cipherTxtFi, "%02X", &ch) != EOF) {
if (ch != '\n') {
if (fileCharCount % potKeyL == 0){
int asciiInd = (int)ch;
freqCounter[asciiInd] += 1;
nThCharCount++;
}
}
fileCharCount++;
}
fclose(cipherTxtFi);
float frequenciesArray[256] = { 0 };
float sumq_iSq = 0;
int k;
for (k = 0; k < 256; k++){
frequenciesArray[k] = freqCounter[k] / (float)nThCharCount;
}
for (k = 0; k < 256; k++){
sumq_iSq += frequenciesArray[k] * frequenciesArray[k];
printf("%f \n", sumq_iSq);
}
if (maxFreq < sumq_iSq) {
maxFreq = sumq_iSq;
winKL = potKeyL;
}
}
return winKL;
}
You are trying to read an hexadecimal integer with fscanf() (format "%02X", where X means "integer in hex format") and store it into a char.
Unfortuantely fscanf() just receives the address of the char and doesn't know that you've not provided the address of an int. As int is larger than a char, the memory gets corrupted.
A solution could be:
int myhex;
while (fscanf(cipherTxtFi, "%02X", &myhex) != EOF) {
ch = myhex;
...

Resources