0

I'm trying to invoke a simple C Program from a python script (as a use case for another complex problem) but for some reason that I didn't understand, the C program not working the way I expect.

C Program testC.c:

#include <stdio.h>

int main(void){
    int num;
    printf("Inside C Program!\n");
    printf("Enter a Number: ");
    scanf("%d", &num);
    printf("%d\n", num*num);
    return 0;
}

Python Program:

import subprocess

def run_c():
    subprocess.call(['gcc', '-o', 'c', 'testC.c'])
    subprocess.call('./c.exe')

def main():
    print("Inside Python Code")
    run_c()
    print('Task is done')

if __name__ == '__main__':
    main()

Expected Output:

Inside Python Code
Inside C Program!
Enter a Number: 5
25
C Program is over
Task is done

Actual Output:

Inside Python Code
5     <-- For some reason, I've to enter the num here to let the program execute.
Inside C Program!
Enter a Number: 25
C Program is over
Task is done

as you can see, I must enter the num variable before any printf that actually came before the scanf("%d", &num);. I'll appreciate any help to understand better why that's happening.

Benny
  • 488
  • 5
  • 18
  • 3
    One word: Buffering. Stdout is only line-buffered by default when it's going to a TTY. If you want it to be forced to be flushed, change your C code to use `fflush()`. And if you want to provide the input from your Python code, you'll want to use `stdin=subprocess.PIPE` and `communicate('input here')` instead of `call()`. – Charles Duffy Oct 17 '21 at 19:14
  • 1
    Closely related (but specialized to the TTY case): [Why does printf not flush after the call unless a newline is in the format string?](https://stackoverflow.com/questions/1716296/why-does-printf-not-flush-after-the-call-unless-a-newline-is-in-the-format-strin) – Charles Duffy Oct 17 '21 at 19:16
  • 1
    Or, even more to the point as it covers the non-TTY case: [Results of printf and system() are in the wrong order when output is redirected to a file](https://stackoverflow.com/questions/52534629/results-of-printf-and-system-are-in-the-wrong-order-when-output-is-redirecte) – Charles Duffy Oct 17 '21 at 19:17
  • @CharlesDuffy Ok, I think I'm starting to get it. can you post some documentation about that topic that you recommend reading? – Benny Oct 17 '21 at 19:20
  • 1
    Side note: you probably shouldn't be compiling your C source code every time you try to run it. Build it once, then just run it. – ChrisGPT was on strike Oct 17 '21 at 19:28
  • @Chris yup, you right. I've simplified my code just for the question here :) – Benny Oct 17 '21 at 19:32
  • 1
    Honestly, I'm not sure what documentation I should look for that the above links don't cover. A big part of the answer is just knowing that buffering _exists_, and that `fflush()` causes content sitting in a buffer to be immediately written. Could you be more specific about what questions are still open? – Charles Duffy Oct 17 '21 at 20:03
  • @CharlesDuffy I'm still not getting in 100% why some content still has to sit in the buffer and not be written immediately to the screen, I mean for what purpose? – Benny Oct 17 '21 at 20:12
  • 1
    The purpose is to reduce the number of round-trips from userspace to kernelspace. Context switches are slow, and fully-buffered behavior is only turned on for stdout by default when the standard C library doesn't think its content is going direct to a TTY. It's a throughput-vs-latency tradeoff. – Charles Duffy Oct 17 '21 at 20:13
  • 1
    BTW, part of why it's standard for prompts to be written to stderr instead of stdout (and yes, your shell's prompts go that way) is that stderr is unbuffered by default. (Also, insofar as a prompt is informing the operator that a program is ready to accept a specific kind of input, it falls into the category of diagnostic output). – Charles Duffy Oct 17 '21 at 20:18
  • @CharlesDuffy Thank you so much for your time and for the detailed explanation. I'll keep reading about that. I'll appreciate it if you can upvote my question :)~ – Benny Oct 17 '21 at 20:34

0 Answers0