So I have a program that takes a file and reads in character by character and prints the character and the hexadecimal equivalent.
`
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *labFile;
char buf;
labFile = fopen("lab1.dat", "r");
if (labFile == NULL) perror("Error opening file\n");
while( (buf = fgetc(labFile) ) != EOF){
if(("%x", buf)< 16){
printf("%c 0%x\n", buf, buf);
}
else
printf("%c %x\n", buf, buf);
}
fclose(labFile);
return 0;
}
`
The program works the way I need it to except for one thing. I need the program to output the hex number on top then the character directly underneath the number and this process needs to continue horizontally.
Any help would be greatly appreciated!
You should output the characters as hex first, and save each read in character that has been printed until you run out of columns on your screen. You can then move to the next line, and print out the characters that were saved underneath the hex output.
You can simplify your logic to format your hex output into a single print statement.
When printing out the character, you need to have a plan to represent non-printable characters. In the sample program below, we handle it by printing two consecutive dots.
void print_chars (unsigned char *p, int num) {
int i;
for (i = 0; i < num; ++i) {
printf("%s%c%s",
isprint(p[i]) ? " " : ".",
isprint(p[i]) ? p[i] : '.',
(i < num-1) ? " " : "\n");
}
}
int main() {
FILE *labFile;
char buf;
int count = 0;
int num = COLUMNS/3;
char printed[num];
labFile = fopen("lab1.dat", "r");
if (labFile == NULL) perror("Error opening file\n");
while( (buf = fgetc(labFile) ) != EOF) {
printf("%s%02x", count ? " " : "", buf);
printed[count++] = buf;
if (count == num) {
count = 0;
putchar('\n');
print_chars(printed, num);
}
}
fclose(labFile);
if (count) {
putchar('\n');
print_chars(printed, count);
}
return 0;
}
The number of columns is divided by 3 since each character takes about 3 columns for output (2 hex characters, and a space). Retrieving the number of columns is system dependent, but you can just plug in 80 if you wish.
You could do something like this. ASSUMES your lines are < 100 chars long. Not safe.
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *labFile;
char buf[100];
labFile = fopen("lab1.dat", "r");
if (labFile == NULL) perror("Error opening file\n");
while(fgets(buf, 100, labFile)) {
if(rindex(buf, '\n')) *rindex(buf, '\n') = 0;
int i, n = strlen(buf);
for(i = 0; i != n; i++) {
printf("0%x ", buf[i]);
}
printf("\n");
for(i = 0; i != n; i++) {
printf("%c ", buf[i]);
}
printf("\n");
}
fclose(labFile);
return 0;
}
Related
I'm trying to print line numbers in the beginning of the lines without using fgets()
yes, it prints line number well when I input multiple files
but I want to get result like this. Can you guys help me with this?
Now result
1 I'll always remember
2 the day we kiss my lips
3
4 light as a feather
*5 #####localhost ~ $*
expect result
1 I'll always remember
2 the day we kiss my lips
3
4 light as a feather
*#####localhost ~$*
Here is my code:
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE *fp;
int c, n;
n = 1;
for (int i = 1; i < argc; i++) {
if (argc < 2)
fp = stdin;
else
fp = fopen(argv[i], "r");
c = getc(fp);
printf("%d ", n);
while (c != EOF) {
putc(c, stdout);
if (c == '\n')
n++, printf("%d ", n);
c = getc(fp);
}
fclose(fp);
}
return 0;
}
Do not write printf("%d ", n); when you do not know if there is the next line. Or, otherwise, do printf("%d ", n); only on the beginning of the file and after a newline when you know there is a next char.
#include <stdbool.h> // for bool, true, false
bool previous_character_was_a_newline = true;
while ((c = getc(fp)) != EOF) {
if (previous_character_was_a_newline) {
previous_character_was_a_newline = false;
printf("%d ", n);
}
putc(c, stdout);
if (c == '\n') {
n++;
previous_character_was_a_newline = true;
}
}
Do not write code like n++, printf("%d ", n);, it will be confusing. Strongly prefer:
if (c == '\n') {
n++;
printf("%d ", n);
}
Your implementation outputs the line number before the first line and after each newline, including the one at the end of the file. This causes an extra line number to appear at the end of the file.
Let's define the output more precisely:
you want the line number at the beginning of each line, no output if no line, no line number after the last line.
do you want the line counter to reset to 1 when a new file is read? I assume no, but cat -n does.
do you want to output an extra newline at the end of a non empty file that does not end with a newline? I assume yes but cat -n does not.
Here is a modified version where the answer is no for the first question and yes for the second:
#include <stdio.h>
int output_file(FILE *fp, int line) {
int c, last = '\n';
while ((c = getc(fp)) != EOF) {
if (last == '\n') {
printf("%d\t", line++);
}
putchar(c);
last = c;
}
/* output newline at end of file if non empty and no trailing newline */
if (last != '\n') {
putchar('\n');
}
return line;
}
int main(int argc, char *argv[]) {
int n = 1;
if (argc < 2) {
n = output_file(stdin, n);
} else {
for (int i = 1; i < argc; i++) {
FILE *fp = fopen(argv[i], "r");
if (fp == NULL) {
perror(argv[i]);
} else {
n = output_file(fp, n);
fclose(fp);
}
}
}
return 0;
}
Attempting to create a program that reasons in a large Text File and filled them into Rows + Columns. Eventually I'll have to computer best path but having trouble just implementing an Array that can store the values.
#include <stdio.h>
#include <stdlib.h>
//max number of characters to read in a line. //MAXN=5 means 4 chars are read, then a \0 added in fgets. See reference for functionality
#define MAXN 100L
int main(void) //char** argv also ok {
int i=0, totalNums, totalNum,j=0;
size_t count;
int numbers[100][100];
char *line = malloc(100);
FILE* inFile ;
inFile = fopen("Downloads/readTopoData/topo983by450.txt", "r"); //open a file from user for reading
if( inFile == NULL) { // should print out a reasonable message of failure here
printf("no bueno \n");
exit(1);
}
while(getline(&line,&count, inFile)!=-1) {
for(;count>0; count--,j++)
sscanf(line, "%d", &numbers[i][j]);
i++;
}
totalNums = i;
totalNum = j;
for(i=0;i<totalNums; i++){
for(j=0;j<totalNum;j++){
printf("\n%d", numbers[i][j]);
}
}
fclose(inFile);
return 0;
}
count does not tell you how many numbers there are. Further: sscanf(line, "%d", &numbers[i][j]); will just scan the same number every time.
So this
for(;count>0; count--,j++)
sscanf(line, "%d", &numbers[i][j]);
should be something like:
j = 0;
int x = 0;
int t;
while(sscanf(line + x, "%d%n", &numbers[i][j], &t) == 1)
{
x += t;
++j;
}
where x together with %n helps you move to a new position in the string when a number has been scanned.
Here is a simplified version that scans for numbers in a string:
#include <stdio.h>
int main(void) {
char line[] = "10 20 30 40";
int numbers[4];
int j = 0;
int x = 0;
int t;
while(j < 4 && sscanf(line + x, "%d%n", &numbers[j], &t) == 1)
{
x += t;
++j;
}
for(t=0; t<j; ++t) printf("%d\n", numbers[t]);
return 0;
}
Output:
10
20
30
40
As the title suggests, I don't know where my mistake is with binary.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char binary[360];
void printstringasbinary(char* s)
{
// A small 9 characters buffer we use to perform the conversion
char output[9];
while (*s)
{
// Convert the first character of the string to binary using itoa.
// Characters in c are just 8 bit integers, at least, in noawdays computers.
itoa(*s, output, 2);
strcat(binary, output);
++s;
}
}
int main(int argc, char *argv[])
{
int i, n;
//printf("argc: %i\n", argc);
if (argc != 3)
{
puts("Converter [Text] [hex|dec|bin]");
return 0;
}
FILE *f = fopen("Output.txt", "a");
for (i = 0; i < strlen(argv[0]); i++)
{
if (strcmp(argv[2], "hex") == 0)
fprintf(f, "%X ", (unsigned int) argv[1][i]);
else if (strcmp(argv[2], "dec") == 0)
fprintf(f, "%i ", (unsigned int) argv[1][i]);
else if (strcmp(argv[2], "bin") == 0)
for (n = 0; n < strlen(argv[1]); n++)
{
printstringasbinary(argv[1][i]);
}
fprintf(f, "%s ", binary);
}
fclose(f);
return 0;
}
You iterate through the characters of argv[1][i], whereas i can take on values up to the string length of argv[0]. Depending on whether argv[0] is "longer" than argv[1], this can lead to a seg fault.
Did you mean printstringasbinary(argv[1][n]) instead of printstringasbinary(argv[1][i])? BTW: why - as pointed out by LPs - do you iterate through argv[1] at all?
for (i = 0; i < strlen(argv[0]); i++)
....
for (n = 0; n < strlen(argv[1]); n++)
{
printstringasbinary(argv[1][n]);
}
I'm trying to use char for identifying the outcome of the text.
For example, i have a file.txt which contains letters like: iiixxiix
I would like to replace the i's with numbers: 123xx67x and so on.
What should I be doing, to get such outcome? I can't seem to use int to replace a char ( srt[i] = c; ) and I have no idea how to move foward from the problem.
#include <stdio.h>
int main()
{
FILE *fp;
char str[60];
int i;
int c = 1;
/* opening file for reading */
fp = fopen("file.txt" , "r");
if(fp == NULL)
{
perror("Error opening file");
return(-1);
}
if( fgets (str, 22, fp)!=NULL )
{
for (i = 0; i < 22; i++)
{
if (str[i] == 'i')
{
str[i] = '0';
}
printf("%c", str[i]);
}
}
fclose(fp);
return(0);
}
The C specification requires that all digit characters are encoded contiguously. And if you look at the common and mostly used ASCII encoding you will see that the digits are encoded from 48 to 57.
That means it's very easy to use the integer index i (modulo 10) and add '0' to get the characters.
Simple example:
for (int i = 0; i < 22; ++i)
{
printf("Index %d to character '%c'\n", i, (char) (i % 10 + '0'));
}
I'm reading:
22:5412:99:00 (...)
From a text file using (ch=fgetc(fp)) != EOF because I don't have only those numbers to read.
Identifying a number is easy with if(ch >= 48 && ch <= 57) but the thing is I want to put those numbers 22, 5412 into an array of integers. However when I read a char it reads part of number since each number is char.
It gets 2 (and not 22 like I want to) and in the next iteration reads the other 2. How can I save each set of numbers into it's own integer?
I hope I was clear enough, thanks!
My idea is to read in each char, and if it is a digit append it to a buffer. Whenever we get a non-digit, we just read the contents of the buffer as a string using sscanf, and clear the buffer for the next value.
#include <stdio.h>
#include <stdlib.h>
int read_buffer(char* buffer, int* sz)
{
int ret;
if (*sz==0) return 0;
buffer[*sz]='\0'; //end the string
sscanf(buffer,"%d", &ret); //read the contents into an int
*sz=0; // clear the buffer
return ret;
}
int main()
{
char buffer[1000];
int sz=0;
char ch;
FILE* input=fopen("input.txt","r");
// "input.txt" contains 22:5412:99:00
while ((ch=fgetc(input))!=EOF)
{
int number;
if (isdigit(ch))
{
buffer[sz++]=ch; // append to buffer
}
else
{
printf("Got %d\n",read_buffer(buffer,&sz)); // read contents of buffer and clear it
}
}
if (sz) // check if EOF occured while we were reading a number
printf("Got %d\n",read_buffer(buffer,&sz));
fclose(input);
return 0;
}
You would need to store the numbers as a string or a char* and use atoi to actually convert it to a number. http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
Assuming your pattern is of the type NN:NNNN:NN:NN, parse on the delimiter, feeding characters into a buffer:
int idx = 0, nIdx = 1;
int firstN, secondN, thirdN, fourthN;
char buf[5];
...
while ((ch=fgetc(fp)) != EOF) {
if (ch != ':') {
buf[idx++] = ch;
}
else {
buf[idx] = '\0';
idx = 0;
switch (nIdx++): {
case 1: firstN = atoi(buf); break;
case 2: secondN = atoi(buf); break;
case 3: thirdN = atoi(buf); break;
}
}
}
buf[idx] = '\0';
fourthN = atoi(buf);
...
I did a full program out of the previous post -- and some testing :-)
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
/* fill `array` with at most `siz` values read from the stream `fp` */
/* return the number of elements read */
size_t fillarray(int *array, size_t siz, FILE *fp) {
int ch;
size_t curr = 0;
int advance_index = 0;
while ((ch = fgetc(fp)) != EOF) {
if (isdigit((unsigned char)ch)) {
array[curr] *= 10;
array[curr] += ch - '0';
advance_index = 1;
} else {
if (advance_index) {
advance_index = 0;
curr++;
if (curr == siz) { /* array is full */
break;
}
}
}
}
return curr + advance_index;
}
int main(void) {
int array[1000] = {0};
int n, k;
n = fillarray(array, 1000, stdin);
if (n > 0) {
printf("%d values read:\n", n);
for (k=0; k<n; k++) {
printf(" %d", array[k]);
}
puts("");
} else {
fprintf(stderr, "no data read\n");
}
return 0;
}
And a test run
$ ./a.out
24555:76423 foobar 76235 jgfs(8) jhg x86-64 passw0rd RS232
[CTRL+D]
8 values read:
24555 76423 76235 8 86 64 0 232