Need help in C printf formatted output - c

I am displaying a partition table, and the table is displayed somewhat like:
Number Device name Partition type Size in MB
------------------------------------------------------------
1 /dev/sda1 NTFS 300
2 /dev/sda2 *Win95 FAT32 99
3 /dev/sda3 Unknown 128
4 /dev/sda4 NTFS 19472
120 /dev/sda120 NTFS 3000
*=Active partition
Now for displaying the above, we are using formatted output printf and the format string is
"%-6d=partition number %-25.25s=device name %c=active partition %-30.30s=part type %7Ld=size"
Now i want to display the same partition table, but with some slight modification, such that the gaps in partition slots would be displayed by a range, like:
5-119 /dev/sda5.../dev/sda119 Empty 0
I am using the formatted string as:
%d-%-6d=partition range %s%d...%s%d=(/dev/sda5.../dev/sda119) %c %-30.30s %7Ld
but it does not help me.
What should be the correct format string? I am using a gcc compiler.

I think you need to use snprintf() to prepare the two composite strings, and then a simpler printf() to do the actual printing. Since you've not shown your actual code, we have to guess at everything, which is a nuisance...
int min = 5;
int max = 119;
char *dev = "/dev/sda";
char num_range[32];
char dev_range[60];
snprintf(num_range, sizeof(num_range), "%d-%d", min, max);
snprintf(dev_range, sizeof(dev_range), "%s%d...%s%d", dev, min, dev, max);
printf("%-10s %-50.50s %c%-30.30s %7d", num_range, dev_range, ' ', "Empty", 0);
You specified %-25.25s for a single device, so it isn't clear whether you should double that for the range, or you should use some other value (or even the same value); you'll need to tweak that part of the format string to suit yourself. This technique is also how I get a colon at the end of a name — format the name and the colon into a string, and then format that string into the final print operation.

Related

"No Output" result in C?

I was doing a programming question and one of the sample output is 64197148392731290. My code for that question is correct as it is giving me the right answers for other test cases (output for those test cases are in single digit).
I understand that there will be too many iterations for the test case which has 64197148392731290 as output. So what should I do to get correct answer for that test case too.
Here is the code :
#include<stdio.h>
#include<string.h>
int main() {
int test_case;long long int i, j, count, n, k, k1;
scanf("%d", &test_case);
while(test_case--) {
scanf("%lld%lld", &n, &k);
char a[n];
count=0;
k1=k;
scanf("%s", a);
while(k1--) {
strcat(a,a);
}
for(i=0;i<(n*k);i++) {
if(a[i]=='a') {
for(j=(i+1);j<(n*k);j++) {
if(a[j]=='b') {
count++;
}
}
}
}
printf("%lld\n", count);
}
return 0;
}
Sample Input and Output :
Input:
3
4 2
abcb
7 1
aayzbaa
12 80123123
abzbabzbazab
Output:
6
2
64197148392731290
My task is to count the number of subsequences "ab" (not necessarily consecutive) in the new string. The first line of the input contains an integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains two integers N and K, denoting the length of the initial string S and the number of repetitions respectively.
The second line contains a string S. Its length is exactly N, and each of its characters is a lowercase English letter.
If you are trying to store input in "int" that wont work coz this number its out of range, change it to "long long int"
Well the previous answer was sure wrong. Thanks for the code.
Sorry don't have time for detailed study but preliminary analysis tells me that maybe the error is because you are trying to store a sting of length 2n in a[n]. It works for smaller values since when you declare
char a[n];
^
variable known at runtime
it actually allocates a large block so that any value of n within range is possible. For large values strcat(a,a) will probably fail.
Basically somewhere down the line the string becomes corrupt. Most probably that is because of strcat. I suggest remove strcat, do something else to a similar effect.

Basic C Matrix segmentation memory allocation

I tried to run this program through the terminal and this error showed up.
"Segmentation Fault: 11"
I would like to know why . What this program does is, it reads a .ppm file and it saves it's information in a matrix variable of type Pixel, so, a PPM file is basically composed by: the first line is going to be "P3" by default, second line the size of the matrix, and the third line the highest value possible for a Pixel attribute, the other lines will have 3 integers of maximum value of 255, so for each member of the matrix there will be a pixel R, G, B.
what I tried to do in the function save_image, first recognize if we are dealing with a ppm file(checking if there is a P3 in the first line), then read the number of rows and columns for the matrix, then it creates a new matrix using the malloc function, then it will save the data in the lines of the file to the .r and .g and .b of the variable myImg.
I am very new to debugging/programming so I'm sorry if this isn't enough information but I tried my best.
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int r;
int g;
int b;
}Pixel;
void save_image(FILE* img, Pixel ** newImg) {
int i;
int j;
int fcount;
int scount;
int count;
int dcc;
char init[3];
fscanf(img,"%s",init);
if(init[0]=='P' && init[1]=='3'){
printf("worked!\n");
fscanf(img,"%d %d",&j,&i);
fscanf(img, "%d",&dcc);
*newImg = (Pixel*)malloc(sizeof(Pixel) * i);
for ( count = 0; count < i ; ++count)
{
newImg[count] = (Pixel*)malloc(sizeof(Pixel) * j);
}
for (fcount = 0; fcount <= i ; ++fcount)
{
for (scount = 0; scount <= j; ++scount)
{
fscanf(img,"%i %i %i",&newImg[i][j].r,&newImg[i][j].g,&newImg[i][j].b);
}
}
}
else
printf("Type of file not recognized\n");
fclose(img);
}
int main(int argc, char const *argv[])
{
FILE* image;
Pixel myImg;
Pixel** newImg;
**newImg = myImg;
image = fopen(argv[1],"r");
save_image(image,newImg);
return 0;
}
The program fails because the initial malloc for newImg[] is malloc'ing some multiple of the size of Pixel rather than size of pointer to Pixel combined with problems with the passing of the pointer to the newImg as a parameter to the save_image() function. See my comment about where the variable newImg should be defined and the desirable modification to the declaration of the save_image() function
Given the was the posted code is written, it seems to be expecting the 'plain' .ppm file format
and the posted code is failing to allow for any embedded comments within the file
given this description of the format of a .ppm file:
The format definition is as follows. You can use the libnetpbm C subroutine library to read and interpret the format conveniently and accurately.
A PPM file consists of a sequence of one or more PPM images. There are no data, delimiters, or padding before, after, or between images.
Each PPM image consists of the following:
A "magic number" for identifying the file type. A ppm image's magic number is the two characters "P6".
Whitespace (blanks, TABs, CRs, LFs).
A width, formatted as ASCII characters in decimal.
Whitespace.
A height, again in ASCII decimal.
Whitespace.
The maximum color value (Maxval), again in ASCII decimal. Must be less than 65536 and more than zero.
A single whitespace character (usually a newline).
A raster of Height rows, in order from top to bottom. Each row consists of Width pixels, in order from left to right. Each pixel is a triplet of red, green, and blue samples, in that order. Each sample is represented in pure binary by either 1 or 2 bytes. If the Maxval is less than 256, it is 1 byte. Otherwise, it is 2 bytes. The most significant byte is first.
A row of an image is horizontal. A column is vertical. The pixels in the image are square and contiguous.
In the raster, the sample values are "nonlinear." They are proportional to the intensity of the ITU-R Recommendation BT.709 red, green, and blue in the pixel, adjusted by the BT.709 gamma transfer function. (That transfer function specifies a gamma number of 2.2 and has a linear section for small intensities). A value of Maxval for all three samples represents CIE D65 white and the most intense color in the color universe of which the image is part (the color universe is all the colors in all images to which this image might be compared).
ITU-R Recommendation BT.709 is a renaming of the former CCIR Recommendation 709. When CCIR was absorbed into its parent organization, the ITU, ca. 2000, the standard was renamed. This document once referred to the standard as CIE Rec. 709, but it isn't clear now that CIE ever sponsored such a standard.
Note that another popular color space is the newer sRGB. A common variation on PPM is to substitute this color space for the one specified.
Note that a common variation on the PPM format is to have the sample values be "linear," i.e. as specified above except without the gamma adjustment. pnmgamma takes such a PPM variant as input and produces a true PPM as output.
Strings starting with "#" may be comments, the same as with PBM.
Note that you can use pamdepth to convert between a the format with 1 byte per sample and the one with 2 bytes per sample.
All characters referred to herein are encoded in ASCII. "newline" refers to the character known in ASCII as Line Feed or LF. A "white space" character is space, CR, LF, TAB, VT, or FF (I.e. what the ANSI standard C isspace() function calls white space).
Plain PPM
There is actually another version of the PPM format that is fairly rare: "plain" PPM format. The format above, which generally considered the normal one, is known as the "raw" PPM format. See pbm for some commentary on how plain and raw formats relate to one another and how to use them.
The difference in the plain format is:
There is exactly one image in a file.
The magic number is P3 instead of P6.
Each sample in the raster is represented as an ASCII decimal number (of arbitrary size).
Each sample in the raster has white space before and after it. There must be at least one character of white space between any two samples, but there is no maximum. There is no particular separation of one pixel from another -- just the required separation between the blue sample of one pixel from the red sample of the next pixel.
No line should be longer than 70 characters.
Here is an example of a small image in this format.
P3
# feep.ppm
4 4
15
0 0 0 0 0 0 0 0 0 15 0 15
0 0 0 0 15 7 0 0 0 0 0 0
0 0 0 0 0 0 0 15 7 0 0 0
15 0 15 0 0 0 0 0 0 0 0 0
There is a newline character at the end of each of these lines.
Programs that read this format should be as lenient as possible, accepting anything that looks remotely like a PPM image.

extract epoch causes data overlapping postgres

I'm working with postgres trying to extract the epoch time from a column that is a timestamp
this is the stored procedure:
CREATE OR REPLACE FUNCTION epochtime(sampleid integer, starttime timestamp without time zone, stoptime timestamp without time zone)
RETURNS text AS
$BODY$DECLARE
result text;
BEGIN
SELECT INTO result string_agg(concat_ws(',',epochres), ',')
FROM (
Select extract('epoch' from "Timestamp") as epochres from "Results"
where "SampleID"=sampleid and "Timestamp" >= starttime
and "Timestamp" <= stoptime order by "Timestamp" asc ) res;
return result;
END$BODY$
LANGUAGE plpgsql VOLATILE
C function where the stored procedure is being called:
static int getEpoch(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const
objv[]){
Tcl_Obj *result;
char sampleid[15];
char repStartTime[256];
char repStopTime[256];
int length;
int lengthTwo;
int lengthThree;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "number of argument error");
return TCL_ERROR;
}
strcpy(sampleid, Tcl_GetStringFromObj(objv[1], &lengthThree));
strcpy(repStartTime, Tcl_GetStringFromObj(objv[2], &length));
strcpy(repStopTime, Tcl_GetStringFromObj(objv[3], &lengthTwo));
char command[256];
PQclear(res);
strcpy(command, "Select \"epochtime\"('");
strcat(command, sampleid);
strcat(command,"','");
strcat(command, repStartTime);
strcat(command,"','");
strcat(command, repStopTime);
strcat(command, "')");
res = PQexec(conn,command);
result = Tcl_GetObjResult(interp);
Tcl_SetStringObj(result, PQgetvalue(res,0,0), strlen(PQgetvalue(res,0,0)));
return TCL_OK;
}
for small number of data i would say around 700 numbers it works fine, but if i try to get a lot of numbers like 10000 or something like that it causes a segmentation fault in the program and if i run the query within the command line it overlaps all the result, literally the numbers look like they are on top of each other
example small amount of records in the column:
example large amount of records in the column:
like i said everything works like it should with the small amount of records but i need it to work the same way with the large amount of records.
The problem that you have is that you concatenate all epochs into a single string and that leads to a buffer overrun when you have many epochs. In other words, when returning many epochs, the resulting string is larger than the allocated memory for the result, leading to the segmentation fault.
The overprinting issue in pgAdmin is just a side effect. pgAdmin is bad with long strings.
A solution would be to simply return the selection of epochs to your C program as individual records and do any concatenation there. You should allocate a string buffer large enough to hold all epochs in a single string, which you could estimate from the number of epochs returned, multiplied by the typical epoch length which appears to be 10 characters in your case (plus the separator and space, obviously, making it 12).
But do you really need to have all epochs in a single string?

snprintf + Pebble

I'm developing for Pebble and I'm off to a rough start.
I'm trying to populate a text_layer with 2 strings and 2 values, something like this:
WAIT AVG: 3 MAX: 5
Since malloc is not supported in Pebble SDK, I can't use sprintf, hence I'm stuck with snprintf. The following code only prints "4":
srand(time(NULL));
int average = (rand()%6)+1;
int maximum = average + 2;
static char *avgText="WAIT AVG: ";
static char *maxText="MAX: ";
snprintf(labelText,sizeof(avgText) + sizeof(average) + sizeof(maxText) + sizeof(maximum),"%s %d %s %d",avgText,average,maxText,maximum);
Any help would be greatly appreciated. I know that I can create 4 separate TextLayers but that's kind of a last resort for me.
You're just using snprintf wrong. ;-)
The second parameter (which you're trying to calculate, badly) is the length of the character array that you're printing into, not the number of characters you're trying to write.
Something like this should work:
char labelText[64]; // Is this big enough?
snprintf(labelText, 64,"%s %d %s %d",avgText,average,maxText,maximum);
sizeof(avgText) and sizeof(maxText) are sizes of pointers, not array sizes. See e.g. here. Change your code to
static char avgText[] = "WAIT AVG: ";
static char maxText[] = "MAX: ";
in order to make them arrays.
edit:
Further note, that sizeof(average) is the size in bytes average covers internally, not how many bytes a decimal representation would consume.
edit2:
As Roddy's answer says, it's wrong to calculate the size we want to have and pass that size to snprintf as an actual buffer size. We can, however, calculate the size we want to have provided there is a reasonable upper bound (e.g. with 32 bit int, 10 bytes (without 0-terminator) are always sufficient, but maybe you can give a lower upper bound in your use case):
char labelText [
sizeof avgText - 1 + 10 +
sizeof maxText - 1 + 10 + 3 + 1
];
/* sizeof avgText counts the 0-terminator, so does sizeof maxText, hence
the -1, two times 10 for the `int` (or any reasonable upper bound you have),
3 spaces and the 0-terminator. */
and you could even use sprintf. With snprintf, you can do:
snprintf(labelText, sizeof labelText,"%s %d %s %d", avgText, average, maxText, maximum);
HTH
read the man page of snprintf() properly. it says, the second argument size is used to refer to the number of bytes to be written.
sizeof (avgText) and sizeof(maxText)is not gonna work here. It refers to the size of the pointer, not the length of the array it holds. Maybe you want to use strlen() for the string length.
So this worked:
srand(time(NULL));
static char labelText[]="WAIT AVG: xxxxx MAX: xxxxxx";
int average = (rand()%6)+1;
int maximum = average + 2;
static char avgText[]="WAIT AVG: ";
static char maxText[]="MAX: ";
snprintf(labelText,sizeof(labelText),"%s %d %s %d",avgText,average,maxText,maximum);
text_layer_set_text(waitField,labelText);
thanks guys

Parsing a file in C

I need parse through a file and do some processing into it. The file is a text file and the data is a variable length data of the form "PP1004181350D001002003..........". So there will be timestamps if there is PP so 1004181350 is 2010-04-18 13:50. The ones where there are D are the data points that are three separate data each three digits long, so D001002003 has three coordonates of 001, 002 and 003.
Now I need to parse this data from a file for which I need to store each timestamp into a array and the corresponding datas into arrays that has as many rows as the number of data and three rows for each co-ordinate. The end array might be like
TimeStamp[1] = "135000", low[1] = "001", medium[1] = "002", high[1] = "003"
TimeStamp[2] = "135015", low[2] = "010", medium[2] = "012", high[2] = "013"
TimeStamp[3] = "135030", low[3] = "051", medium[3] = "052", high[3] = "043"
....
The question is how do I go about doing this in C? How do I go through this string looking for these patterns and storing the values in the corresponding arrays for further processing?
Note: Here the seconds value in timestamp is added on our own as it is known at each data comes after 15 seconds.
edit: updated to follow your specs.
While your file seems to be variable length, your data isn't, you could use fscanf and do something like this:
while(fscanf(file,"PP%*6d%4d", &timestamp, &low, &medium, &high))
{
for(int i = 0; fscanf(file, "D%3d%3d%3d", &low, &medium, &high); i++)
{
timestamp=timestamp*100+i*15;
//Do something with variables (e.g. convert to string, push into vector, ...)
}
}
Note that this reads the data into integers (timestamp, low, medium and high are int's), A string version looks like this (timestamp, low, medium and high are char arrays):
int first[] = {'0', '1', '3', '4'};
int second[] = {'0','5'};
while(fscanf(file,"PP%*6d%4c", &timestamp, &low, &medium, &high))
{
for(int i = 0; fscanf(file, "D%3c%3c%3c", &low, &medium, &high); i++)
{
timestamp[i][4]=first[i%4];
timestamp[i][2]=second[i%2];
}
}
edit: some more explanation about the formatting string, with %*6d I mean: look for 6 digits and discard them (* means: do not put in a variable). %4d or %4c means in this context the same (as 1 digit will be one char), but we do save them in corresponding variables.
As long as your patterns aren't variable length, you could simply use fscanf. If you need something more complex, you might try PCRE, but for this case I think sscanf will suffice.
I wouldn't recommend using fscanf directly on input data because it is very sensitive to the in data, if one byte is wrong and suddenly doesn't the format specifier then you could in worst case a memory overwrite.
It is better to either in using fgetc and parse as it comes in or read into a buffer (fread) and process it from there.
Simply Parsing? Here it is!!
UPDATE: Checkout KillianDS's code above. Thats even better!!
[STEP 1] Search for /n ( or CR+LF)
[STEP 2] Starting from the first character on the line, U know the no. of characters each datafield occupies. Read that many characters from the file.
use atoi() to convert the character data to int
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
Repeat for all fields.

Resources