String search C program for command prompt - c

I wrote C program of searching string. The problem is MyStrstr() function doesn't work with
command prompt. It only works with IDE. So, can anyone advise me how to fix the code for working with command prompt. With regards...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ARGUMENT_COUNT 3
#define FILE_INDEX 2
#define SEARCH_INDEX 1
#define BUFFER 256
#define SUCCESS 0
#define ERRCODE_PARAM 1
#define ERRCODE_FILENAME 2
#define MSG_USAGE "String Search Program === EXER5 === by Newbie\nUsage: %s Search_String fileName"
#define MSG_ERROR "Can not open file. [%s]"
char* MyStrstr(char* pszSearchString, char* pszSearchWord);
int main(int argc, char* argv[])
{
FILE* pFile = NULL;
char szData[BUFFER];
char* pszCutString = NULL;
if(argc != ARGUMENT_COUNT) {
printf(MSG_USAGE, argv[0]);
return ERRCODE_PARAM;
}
pFile = fopen(argv[FILE_INDEX], "r");
if(pFile == NULL) {
printf(MSG_ERROR, argv[FILE_INDEX]);
return ERRCODE_FILENAME;
}
pszCutString = MyStrstr(szData, argv[SEARCH_INDEX]);
if(pszCutString != NULL) {
printf("%s", pszCutString);
}
fclose(pFile);
pFile = NULL;
return SUCCESS;
}
char* MyStrstr(char* pszSearchString, char* pszSearchWord) {
int nFcount = 0;
int nScount = 0;
int nSearchLen = 0;
int nIndex = 0;
char* pszDelString = NULL;
char cSLen = 0;
size_t len = 0;
if(pszSearchString == NULL || pszSearchWord == NULL) {
return NULL;
}
while(pszSearchWord[nSearchLen] != '\0') {
nSearchLen++;
}
if(nSearchLen <= 0){
return pszSearchString;
}
cSLen = *pszSearchWord++;
if (!cSLen) {
return (char*) pszSearchString;
}
len = strlen(pszSearchWord);
do {
char cMLength;
do {
cMLength = *pszSearchString++;
if (!cMLength)
return (char *) 0;
} while (cMLength != cSLen);
} while (strncmp(pszSearchString, pszSearchWord, len) != 0);
return (char *) (pszSearchString - 1);
}

You want to open a file, search the contents of that file for a string and return/print that. You are instead doing:
char szData[256]; // <-- making an uninitialized buffer
char* pszCutString = NULL;
pFile = fopen(argv[2], "r"); // <-- Opening a file
pszCutString = MyStrstr(szData, argv[1]); // <-- searching the buffer
if(pszCutString != NULL) {
printf("%s", pszCutString);
}
fclose(pFile); // <-- Closing the file
So you never fill your buffer szData with the contents of the file noted in argv[2]. You're trying to search an uninitialized buffer for a string. You're luck the result is just "no output comes out".
You need to take the contents of the file in argv[2] and place it in the buffer szData then do the search. This could be accomplished by adding a call to a function like read() or fscanf()
Note 1:
I assume when you say this "worked" in the IDE, the code was a little different and you weren't using the command line arguments.
Note 2:
you should also check to fopen() worked before trying to read from/close pFile, and if your file is possibly larger than 256 characters you will need to change your code to either have a dynamically sized string, or you'll need to loop the buffer fills (but then you have to worry about breaking a word apart), or some other mechanism to check the full file.

Related

How would I create an array of char* after reading an unknown number of strings (each of unknown length) from a file? [duplicate]

This question already has answers here:
How should character arrays be used as strings?
(4 answers)
Closed 12 months ago.
I have a file with an unknown number of strings and each of these strings is of an unknown length.
I would like to make each line of the file its own string in an array of strings.
I tried to use dynamic allocation in a char** array, but I don't think I'm approaching this correctly.
Below is the code I have tried. It's getting stuck in an infinite loop, and I can't figure out why.
(The text file I'm reading from ends with a line break, by the way.)
#include <getopt.h> //for getopts
#include <sys/stat.h> //to do file stat
#include <dirent.h>
#include <string.h>
#include <pwd.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h> //user macros
#include <stdlib.h>
#include <stdbool.h>
#include <libgen.h>
#include <errno.h>
int main(int argc, char *argv[]) {
//storing the filename inside string
char* filename = argv[1];
FILE *fp1 = fopen(filename, "r");
if (fp1 == NULL) {
fprintf(stderr, "Error: Cannot open '%s'. No such file or directory.\n", filename);
return EXIT_FAILURE;
}
/**
* we begin by getting the number of numbers in the file
* the number of numbers = number of lines = number of line breaks
*/
size_t numNumbers = 0;
// while((fscanf(fp1, "%*[^\n]"), fscanf(fp1, "%*c")) != EOF){
// numNumbers = numNumbers + 1;
// }
char c;
while((c = fgetc(fp1)) != EOF){
if(c == '\n'){
numNumbers++;
}
}
fclose(fp1);
FILE *fp2 = fopen(filename, "r");
char** arrayOfStrings = malloc(numNumbers * sizeof(char*));
for(int i = 0; i < numNumbers; i++) {
int len = 0;
if(((c = fgetc(fp1)) != '\n') && (c != EOF)){
len++;
}
arrayOfStrings[i] = malloc(len * sizeof(char));
}
printf("hello1\n");
//for(int i = 0; i < numNumbers; i++){
// fscanf(fp2, "%s", (arrayOfStrings[i]));
//}
fclose(fp2);
// for(int i = 0; i < numNumbers; i++){
// fprintf(stdout, "%s", arrayOfStrings[i]);
// }
return 0;
}
(I'm very new to C, so please go easy on me!)
In C, strings are terminated with a '0' byte, so it looks like your malloc for each string is 1 character too short -- you've only allowed space for the text.
In addition, you mean the count for the size of each line to be a while loop, not an if statement - right now you are counting each line as length "1".
Finally, you are reading off the end of the file in your commented out fscanf code because you haven't closed and reopened it.
Assuming you want to split the input to the strings by the newline character, would you please try:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *filename; // filename to read
char **arrayOfStrings = NULL; // array of strings
char line[BUFSIZ]; // line buffer while reading
char *p; // temporal pointer to the input line
int i, num; // counter for lines
FILE *fp; // file pointer to read
if (argc != 2) {
fprintf(stderr, "usage: %s file.txt\n", argv[0]);
return EXIT_FAILURE;
}
filename = argv[1];
if (NULL == (fp = fopen(filename, "r"))) {
perror(filename);
return EXIT_FAILURE;
}
// read the input file line by line
while (fgets(line, BUFSIZ, fp)) {
if ((p = strrchr(line, '\n'))) *p = '\0'; // remove trailing newline, if any
if ((p = strrchr(line, '\r'))) *p = '\0'; // remove trailing cr character, if any
if (NULL == (arrayOfStrings = realloc(arrayOfStrings, (num + 1) * sizeof(char **)))) {
// enlarge the array according to the line count
perror("realloc");
return EXIT_FAILURE;
}
if (NULL == (arrayOfStrings[num] = malloc(strlen(line) + 1))) {
// memory for the string of the line
perror("malloc");
return EXIT_FAILURE;
}
strcpy(arrayOfStrings[num], line);
num++;
}
// print the strings in the array
for (i = 0; i < num; i++) {
printf("%d %s\n", i, arrayOfStrings[i]);
}
fclose(fp);
return 0;
}
If the input file looks something like:
This
is
the
input.
Then the output will be:
0 This
1 is
2 the
3 input.

C program to print given number of lines from beginning of text file. File name and number of lines from command line argument

I'm writing a program said in this post title. I take reference at this webpage.
https://www.includehelp.com/c-programs/c-program-to-print-given-number-of-lines-of-a-file-like-head-command-in-linux.aspx
Here are the codes from that webpage.
#include <stdio.h>
int main(int argc, char * argv[])
{
FILE *fp; // file pointer
char *line = NULL;
int len = 0;
int cnt = 0;
if( argc < 3)
{
printf("Insufficient Arguments!!!\n");
printf("Please use \"program-name file-name N\" format.\n");
return -1;
}
// open file
fp = fopen(argv[1],"r");
// checking for file is exist or not
if( fp == NULL )
{
printf("\n%s file can not be opened !!!\n",argv[1]);
return 1;
}
// read lines from file one by one
while (getline(&line, &len, fp) != -1)
{
cnt++;
if ( cnt > atoi(argv[2]) )
break;
printf("%s",line); fflush(stdout);
}
// close file
fclose(fp);
return 0;
}
My problem is the getline function. Since I'm not using Linux that function's giving error in my compiler. I tried to change it to fgets function. This is my revised codes.
I got two errors in the line ' while (fgets(&line, bufferLength, fp) != -1)'.
Error: passing argument 1 of 'fgets' from incompatible pointer type.
Error: comparison between pointer and integer.
My question is - how can I modify the program using fgets? Many thanks to anyone who can work this out.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp; // file pointer
char *line = NULL;
int bufferLength = 255;
int cnt = 0;
if( argc < 3)
{
printf("Insufficient Arguments!!!\n");
printf("Please use \"program-name file-name N\" format.\n");
return -1;
}
// open file
fp = fopen(argv[1],"r");
// checking for file is exist or not
if( fp == NULL )
{
printf("\n%s file can not be opened !!!\n",argv[1]);
return 1;
}
// read lines from file one by one
while (fgets(&line, bufferLength, fp) != -1)
{
cnt++;
if ( cnt > atoi(argv[2]) )
break;
printf("%s",line);
fflush(stdout);
}
// close file
fclose(fp);
return 0;
}
Your program should compile and run correctly follows:
//c program to print given number of lines from beginning of a file
//file name and number of lines must be supply as command line argument
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[])
{
FILE* fp; // file pointer
char* line = malloc(255);
int bufferLength = 255;
int cnt = 0;
if( argc < 3)
{
printf("Insufficient Arguments!!!\n");
printf("Please use \"program-name file-name N\" format.\n");
return -1;
}
// open file
fp = fopen(argv[1],"r");
// checking for file is exist or not
if( fp == NULL )
{
printf("\n%s file can not be opened !!!\n",argv[1]);
return 1;
}
// read lines from file one by one
while (fgets(line,bufferLength, fp))
{
cnt++;
if ( cnt > atoi(argv[2]) )
break;
printf("%s",line);
fflush(stdout);
}
// close file
fclose(fp);
free(line);
return 0;
}
we have two main problems, first
char * line = NULL;
line is a line of characters, a string if you want to call it that, so we must reserve enough memory to accommodate a complete line, and we do this with the malloc function, as seen in the program, the other problem we have with fgets, this function returns a pointer therefore we cannot compare the value returned by fgets with an integer, the declaration
while (fgets (line, bufferLength, fp))
is equivalent to running the loop while fgets is other than NULL. Finally we must use line instead of &line, the latter asks for the address of the line pointer, and not the address it points to.
There's no need to keep track of more than a single character. Reading full lines is overkill. Just do:
#include <stdio.h>
#include <stdlib.h>
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = fopen(path, mode);
if( fp == NULL ) {
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
int
main(int argc, char **argv)
{
int count = argc > 1 ? strtol(argv[1], NULL, 10) : 1;
FILE *in = argc > 2 ? xfopen(argv[2], "r") : stdin;
int line = 0;
int c;
while( line < count && ( c = fgetc(in)) != EOF ) {
putchar(c);
if( c == '\n' ) {
line += 1;
}
}
}
Note that I've reversed the order of the arguments, so that stdin is read if only a count is given.

fgets is returning a blank screen

I am new to C, this is my first project and have been teaching myself. Within my program, one of my functions needs to read a line from a file, and store it in a char array. When I trace the program with gdb the array (line[]) is simply zeros. This leads to my program returning the error "Error: a line in the asset file lacks a ':' separator\n"
Here is my code:
//return the line number (0 based) that the cmd is on, -1 if absent
int locateCmd(char cmd[]) {
int lineIndex = -1; //-1, because lineIndex is incramented before the posible return
char cmdTemp[10] = "\0";
//create a compareable cmd with correct cmd that has its remaining values zeroed out
char cmdCmp[10] = "\0";
memset(cmdCmp, 0, sizeof(cmdCmp));
for (int i = 0; i < strlen(cmd); i++) {
cmdCmp[i] = cmd[i];
}
FILE *file = fopen(ASSET_FILE, "r");
//loop until target line is reached
while (strcmp(cmdTemp, cmdCmp) != 0) {
//check if last line is read
if (lineIndex == lineCounter(file)-1) {
return -1;
}
memset(cmdTemp, 0, sizeof(cmdTemp));
char line[61];
fgets(line, 61, file);
//set cmdTemp to the command on current line
lineIndex++;
for (int i = 0; line[i] != ':'; i++) {
cmdTemp[i] = line[i];
//return error if line doesn't contain a ':'
if (line[i] = '\n') {
printf("Error: a line in the asset file lacks a ':' separator\n");
exit(1);
}
}
}
return lineIndex;
}
Some context, this function is passed a command, and its job is to read a document that appears like this:
command:aBunchOfInfoOnTheComand
anotherCommand:aBunchOfInfoOnTheComand
and pick out the line that the passed command (cmd[]) is stored on.
The issue is with the fgets on line 24. I have separated the relevant portion of this code out into a smaller test program and it works fine.
The test program that works is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[]) {
FILE *file = fopen("tutorInfo.txt", "r");
char line[61];
fgets(line, 61, file);
printf("%s\n", line);
}
The proper exicution of my test program leads me to believe other code in my function is causing the issue, but i'm not sure what. It may be important to note, the problematic code has the same imports as my sample program. Any help would be much appreciated.
As OP didn't provide a Minimal, Complete, and Verifiable example, I have to base my answer on the functional description provided in the question.
I already covered some error and corner cases, but I'm sure I missed some. The approach is also inefficient, as the file is read over and over again, instead of parsing it once and returning a hash/map/directory for easy lookup. In real life code I would use something like GLib instead of wasting my time trying to re-invent the wheel(s)...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE_BUFFER_LENGTH 200
unsigned int locateCmd(FILE *fh, const char *key, const char **cmd_line) {
unsigned int found = 0;
size_t key_length = strlen(key);
*cmd_line = NULL;
/* make sure to start read from start of file */
rewind(fh);
unsigned int line_no = 0;
static char buffer[LINE_BUFFER_LENGTH];
while (!feof(fh) && (found == 0)) {
// NOTE: EOF condition will be checked on the next iteration
fgets(buffer, sizeof(buffer), fh);
size_t length = strlen(buffer);
line_no++;
if (buffer[length - 1] != '\n') {
printf("line %u is too long, aborting!\n", line_no);
return(0);
}
if ((strncmp(key, buffer, key_length) == 0) &&
(buffer[key_length] == ':')) {
found = line_no;
buffer[length - 1] = '\0'; // strip line ending
*cmd_line = &buffer[key_length + 1];
}
}
return(found);
}
int main(int argc, char *argv[]) {
FILE *fh = fopen("dummy.txt", "r");
if (!fh) {
perror("file open");
return(1);
}
int ret = 0;
while (--argc > 0) {
const char *cmd;
const char *key = *++argv;
unsigned line_no = locateCmd(fh, key, &cmd);
if (line_no != 0) {
printf("key '%s' found on line %u: %s\n", key, line_no, cmd);
ret = 0;
} else {
printf("key '%s' not found!\n", key);
};
}
if (fclose(fh) != 0) {
perror("file close");
return(1);
}
return(ret);
}
Test input dummy.txt:
command:aBunchOfInfoOnTheComand
anotherCommand:aBunchOfInfoOnTheComand
brokenline
foo:bar
toolong:sadflkjaLKFJASDJFLKASJDFLKSAJ DLFKJ SLDKJFLKASDFASDFKJASKLDJFLKASJDFLKJASDLKFJASLKDFJLKASDJFLKASJDLFKJASDKLFJKLASDJFLKSAJDFLKJASDLKFJKLASDJFLKASJDFKLJASDLKFJLKASDJFLKASJDFLKJSADLKFJASLKDJFLKC
Some test runs:
$ gcc -Wall -o dummy dummy.c
$ ./dummy command foo bar
key 'command' found on line 1: aBunchOfInfoOnTheComand
key 'foo' found on line 5: bar
line 6 is too long, aborting!
key 'bar' not found!

Extract a column of a list from a text file in C

This may be a simple question with a straightforward answer, but searching through the site I didn't find anything (maybe because I'm new to C programming) except for python codes, which I already wrote and it's quite inefficient.
Suppose I have a list of data in a timestamps.txt file, formatted like this:
<large integer>, <integer between 1 and 8>
<large integer>, <integer between 1 and 8>
and so on (the file is about 4GB)...
What I want to do is to copy only the second column to another file, say singles.txt.
What I did so far works, but it's a rather naive approach and takes too much time. Here's my code:
int main(int argc, char const *argv[])
{
FILE *input_file;
FILE *output_file;
char ch;
int check = 0;
input_file = fopen("timestamps.txt","r");
output_file = fopen("singles.dat","w");
if (!input_file)
return -1;
while((ch = getc(input_file))!=EOF)
{
if(check==1)
{putc(ch,output_file);putc('\n',output_file);}
if(ch == ',')
check = 2;
else
check -= 1;
}
fclose(input_file);
fclose(output_file);
return 0;
}
I'm sure there is a faster way, but I can't seem to make anything work.
Any help would be much appreciated.
Using fgets and fputs is faster than multiple calls to getc and putc, all you need is a buffer (a little buffer in this case) to store the current line:
int main(int argc, char const *argv[])
{
FILE *input_file;
FILE *output_file;
char buf[128];
char *ptr;
input_file = fopen("timestamps.txt","r");
output_file = fopen("singles.dat","w");
if (!input_file)
return -1; /* use EXIT_FAILURE instead of -1 */
/* you forget to check output_file */
while (fgets(buf, sizeof buf, input_file)) {
ptr = strchr(buf, ','); /* find the comma */
if (ptr != NULL) {
fputs(ptr + 1, output_file); /* +1 to skip the comma */
}
}
fclose(input_file);
fclose(output_file);
return 0;
}
Your idea isn't so bad, but you should make your variable check either 0 or 1, depending on whether you want to copy the current input data or not. And you must reset the check with each new line.
Alternatively, you could countthe current field your are in and copy the data when the field is the one you want.
Here's a version that copies the column want delimited by sep verbatim to the output file:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
FILE *in = stdin;
FILE *out = stdout;
int want = 1;
int col = 0;
int sep = ',';
for (;;) {
int c = getc(in);
if (c == EOF) break;
if (c == sep) {
col++;
} else if (c == '\n') {
col = 0;
putc(c, out);
} else if (col == want) {
putc(c, out);
}
}
return 0;
}
(I've used stdin and stdout, because I was lazy and didn't want to do the flie opening and closing stuff.)

Why can't I close the file

I have a problem when I close the file fc.
Here is my code
#include <stdio.h>
#include <wchar.h>
int main()
{
FILE* fc = fopen("template.txt","rt,ccs=UTF-8");
wchar_t subStr[2300];
fread(subStr,sizeof(wchar_t),2300,fc);
wchar_t* scrStr=new wchar_t[2300];
wcscpy(scrStr,subStr);
fclose(fc);
return 0;
}
The file was probably not opened correctly in the first place. You must check that the 'handle' to the stream returned by fopen is not NULL. The following code checks the file 'handle', with a few bits changed to make it 'reasonable' C.
#include <stdio.h>
#include <wchar.h>
int main()
{
wchar_t* scrStr = NULL;
FILE* fc = fopen("template.txt","rt,ccs=UNICODE");
// Check that the file was opened.
if(NULL != fc)
{
wchar_t subStr[2301];
size_t wcharsRead = fread(subStr, sizeof wchar_t , 2300, fc);
fclose(fc);
// Check if anything was read.
if(0 != wcharsRead)
{
// Terminate the string in the temporary buffer.
subStr[wcharsRead] = `\0`;
// Allocate a smaller string (use new, if you're in C++).
if(scrStr = malloc(1 + sizeof wchar_t * wcharsRead), NULL != scrStr)
{
// Copy the useful bit into the new string.
wcscpy(scrStr, subStr);
}
}
}
else
{
// Do some error handling
printf("Unable to open file. Error code: %d\r\n",errno);
}
// Check if a string was read.
if(NULL != scrStr)
{
// Do something with scrStr
// Free the string once it's finished with (use delete if you're in C++).
free(scrStr);
}
return 0;
}

Resources