0

I have this code:

#include<stdio.h>
#include<stdlib.h>

char *K2G(int k)
{
    static char g[10];
    if (k > 1048576) {
        sprintf(g, "%.2fGB", (float) k / 1048576);
    } else {
        if (k > 1024) {
            sprintf(g, "%.2fMB", (float) k / 1024);
        } else {
            sprintf(g, "%dKB", k);
        }
    }
    printf("%s\n", g);
    return g;
}

main()
{
    FILE *fp;
    int imt = 0, imf = 0, imu = 0;
    char cmt[40], cmf[40], cmti[20], cmfi[20], a[20], b[20];
    while (1) {
        system("clear");
        fp = fopen("/proc/meminfo", "r");
        fgets(cmt, 40, fp);
        fgets(cmf, 40, fp);
        fclose(fp);
        printf("%s%s\n", cmf, cmt);
        sscanf(cmt, "%s%d%s", a, &imt, b);
        sscanf(cmf, "%s%d%s", a, &imf, b);
        imu = imt - imf;
        printf("%s/%s=%d%\n", K2G(imu), K2G(imt), imu * 100 / imt);
        sleep(1);
    }
}

The output I get is something like:

MemFree:          494256 kB
MemTotal:       10258000 kB

9.78GB
9.31GB
9.31GB/9.31GB=95%

The last line always displays the same two values before the equal sign. The output should have been:

MemFree:          494724 kB
MemTotal:       10258000 kB

9.31GB
9.78GB
9.31GB/9.78GB=95%

Why do I get duplicate values when I call function K2G with printf? This is the line giving me the incorrect results:

printf("%s/%s=%d%\n", K2G(imu), K2G(imt), imu * 100 / imt);
Michael Petch
  • 46,082
  • 8
  • 107
  • 198
sonichy
  • 1,370
  • 2
  • 14
  • 17
  • 1
    Please show us the code, the input values, and actual and expected output values. Edit your question to include that information. Without that information it's impossible to help you. – Some programmer dude Nov 05 '15 at 11:23
  • 1
    Please show your code in the question and not in a picture !! – Jabberwocky Nov 05 '15 at 11:28
  • 1
    Please, oh please, don't post images of text, especially links to those images. First of all, it's impossible to copy-paste text from images, second of all links can become stale which make the question useless. – Some programmer dude Nov 05 '15 at 11:28
  • 1
    And also please show input and expected and actual output. – Some programmer dude Nov 05 '15 at 11:30
  • Although Michael answered the question, a couple comments about your code. You should `` and ``. in this _printf_ call `printf("%s/%s=%d%\n", ...` you should be using `%%` to print out a single `%` symbol. It should be `"%s/%s=%d%%\n"` and your `main` function should return an `int`. Declare it as `int main()` – Michael Petch Nov 05 '15 at 12:23

1 Answers1

2

This behaviour is normal, you return a pointer to g which is a static buffer, and on each call this buffer will be overwritten.

So if you do printf(..., K2G(x), K2G(Y),...), the parameters "seen" by printf will both be the same g buffer with it's latest content.

You can do this:

char simu[20];
char simt[20];
strcpy(simu, K2G(imu));
strcpy(simt, K2G(imt));
printf(..., simu, simt,...);

EDIT:

Or you can use another pattern where you have to provide a buffer to K2G:

char *K2G(int k, char *g)
{
    if (k > 1048576) {
        sprintf(g, "%.2fGB", (float) k / 1048576);
    } else {
        if (k > 1024) {
            sprintf(g, "%.2fMB", (float) k / 1024);
        } else {
            sprintf(g, "%dKB", k);
        }
    }
    printf("%s\n", g);
    return g;
}

...

char simu[20];
char simt[20];
K2G(imu, simu);
K2G(imt, simt);
printf(..., simu, simt,...);

This is more transparent and avoids the usage of strcpy.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • 1
    @umläute: what possible advantage does `strncpy` (assumed) have over the suggested plain `strcpy`? – Jongware Nov 05 '15 at 12:18
  • 1
    @jongware `strncpy` wouldn't be my first choice (it can still be abused), but `strcpy` is worse. Where available I usually use a version of BSD's strlcpy (usually you can find it as package libbsd on most distros). If you don't want to pull in a library strlcpy functionality can be replicated). In this case I think `strncpy(simu, K2G(imu), sizeof(imu)-1);` is reasonably safe as long as you don't use strncat. – Michael Petch Nov 05 '15 at 12:34
  • @MichaelPetch: well I suggested `strcpy` because it's in the standard. Of course there are alternatives. But (see http://stackoverflow.com/a/2115072/2564301) problems arise when the programmer is not sure about the string lengths, and that does not appear to be the case here. – Jongware Nov 05 '15 at 12:42