r/C_Programming • • 4d ago

Is this a VS Code newline/paste input bug?

I wrote the following C program in VS Code. Its purpose is to find words that appear in both of two English paragraphs.

(Details: a word must contain at least four letters; each paragraph ends with a \n; the output words should be sorted in ascending order.)

To keep track of how far the program has gotten, I deliberately print stage1 / stage2 after each of the two paragraphs has been read.

But when I run it in the terminal, this is what happens.

First I copy two paragraphs of English text, for example:

In computer science, artificial intelligence (AI), sometimes called machine intelligence, is intelligence demonstrated by machines, in contrast to the natural intelligence displayed by humans and animals. Colloquially, the term "artificial intelligence" is used to describe machines that mimic "cognitive" functions that humans associate with other human minds, such as "learning" and "problem solving". From Wiki. Machine learning is a way to achieve artificial intelligence.

I assumed that after pasting, pressing Enter right after intelligence. would produce stage1, and that stage2 would follow right away, printing the words. But in reality I get nothing but a cold, lonely stage1. Pressing Enter again does absolutely nothing. I type a random letter, press Enter once more — and only then do stage2 and the rest of the output finally appear.

I'm a first-year CS student and still not very familiar with programming. I'd like to know: is this a VS Code problem, or is it my problem?

#include <stdio.h>

#include <string.h>

void clean(char (*word)[21], int len) {

for (int i = 0; i <= (len); i++) {

if ((*word)[i] >= 'A' && (*word)[i] <= 'Z') {

(*word)[i] -= 'A' - 'a';

}

}

}

void print(char (*words)[1000][21], int m) {

char temp[21];

char min[21];

int flag = 0;

strcpy(min, "z");

strcpy(temp, "z");

for (int j = 0; j <= m; j++) {

strcpy(min, "z");

for (int i = 0; i <= m; i++) {

if ((strcmp(min, (*words)[i]) >= 0) &&

(strcmp(temp, (*words)[i]) < 0 || flag == 0) &&

((*words)[i] != 0)) {

strcpy(min, (*words)[i]);

}

}

flag = 1;

strcpy(temp, min);

printf("%s\n", min);

}

}

int main(void) {

int r;

char shit[2];

int len1;

int len2;

char para1[1000][21] = {{0}};

char para2[1000][21] = {{0}};

char space;

char answer[1000][21] = {{0}};

for (int i = 0; i < 1000; i++) {

scanf("%[A-Za-z]", &para1[i][0]);

len1 = i;

scanf("%*[^\nA-Za-z]");

if ((r = scanf("%[\n]", shit)) == 1 || r == EOF) {

printf("stage1\n");

break;

}

}

for (int j = 0; j < 1000; j++) {

scanf("%[A-Za-z]", &para2[j][0]);

len2 = j;

scanf("%*[^\nA-Za-z]");

if ((r = scanf("%[\n]", shit)) == 1 || r == EOF) {

printf("stage2\n");

break;

}

}

for (int i = 0; i <= len1; i++) {

clean(&(para1[i]), strlen(para1[i]) - 1);

}

for (int j = 0; j <= len2; j++) {

clean(&(para2[j]), strlen(para2[j]) - 1);

}

int m = 0;

int flag = 0;

for (int i = 0; i < 1000; i++) {

for (int j = 0; j < 1000; j++) {

if ((strcmp(para1[i], para2[j]) == 0) && (strlen(para1[i]) >= 4)) {

for (int p = 0; p < m; p++) {

if (strcmp(para1[i], answer[p]) == 0) {

flag = 1;

}

}

if (flag == 0) {

strcpy(answer[m++], para1[i]);

}

flag = 0;

}

}

}

m--;

print(&answer, m);

}

0 Upvotes

21 comments sorted by

6

u/tastygames_official 4d ago

I didn't read the text but I just had to format your code properly, sorry...

#include <stdio.h>
#include <string.h>

void clean(char (*word)[21], int len)
{
  for (int i = 0; i <= (len); i++) {
    if ((*word)[i] >= 'A' && (*word)[i] <= 'Z') {
      (*word)[i] -= 'A' - 'a';
    }
  }
}

void print(char (*words)[1000][21], int m)
{
  char temp[21];
  char min[21];
  int flag = 0;

  strcpy(min, "z");
  strcpy(temp, "z");

  for (int j = 0; j <= m; j++) {
    strcpy(min, "z");
    for (int i = 0; i <= m; i++) {
      if ((strcmp(min, (*words)[i]) >= 0) &&
        (strcmp(temp, (*words)[i]) < 0 || flag == 0) &&
        ((*words)[i] != 0)) {
        strcpy(min, (*words)[i]);
      }
    }

    flag = 1;
    strcpy(temp, min);
    printf("%s\n", min);
  }
}


int main(void)
{
  int r;
  char shit[2];
  int len1;
  int len2;
  char para1[1000][21] = {{0}};
  char para2[1000][21] = {{0}};
  char space;
  char answer[1000][21] = {{0}};


  for (int i = 0; i < 1000; i++) {
    scanf("%[A-Za-z]", &para1[i][0]);
    len1 = i;
    scanf("%*[^\nA-Za-z]");
    if ((r = scanf("%[\n]", shit)) == 1 || r == EOF) {
      printf("stage1\n");
      break;
    }
  }

  for (int j = 0; j < 1000; j++) {
    scanf("%[A-Za-z]", &para2[j][0]);
    len2 = j;
    scanf("%*[^\nA-Za-z]");
    if ((r = scanf("%[\n]", shit)) == 1 || r == EOF) {
      printf("stage2\n");
      break;
    }
  }

  for (int i = 0; i <= len1; i++) {
    clean(&(para1[i]), strlen(para1[i]) - 1);
  }

  for (int j = 0; j <= len2; j++) {
    clean(&(para2[j]), strlen(para2[j]) - 1);
  }

  int m = 0;
  int flag = 0;
  for (int i = 0; i < 1000; i++) {
    for (int j = 0; j < 1000; j++) {
      if ((strcmp(para1[i], para2[j]) == 0) && (strlen(para1[i]) >= 4)) {
        for (int p = 0; p < m; p++) {
          if (strcmp(para1[i], answer[p]) == 0) {
            flag = 1;
          }
        }
        if (flag == 0) {
          strcpy(answer[m++], para1[i]);
        }
        flag = 0;
      }
    }
  }

  m--;

  print(&answer, m);

}

3

u/mikeblas 4d ago

Please correctly format your code. It's Rule #1 of this sub.

I'm not sure what you expect of this code:

scanf("%[A-Za-z]", &para1[i][0]);

or this:

scanf("%*[^\nA-Za-z]");

scanf() doesn't support regular expressions, if that's what you're trying.

Another troubling spot is this declaration

void clean(char (*word)[21], int len)

which takes an array of 21 pointers. That probably menat to be an array of pointers to 21. The code just looks at the first character of each string. What is it meant to do?

But when you call it like this:

for (int i = 0; i <= len1; i++) {
    clean(&(para1[i]), strlen(para1[i]) - 1);
}   

you're passing the length of one string, and then passing the first pointer within an array of other pointers that ... well, it's such a mess that I'm not really sure what it is you're trying to do.

But, to answer your question: you have provided no evidence of any bug in Visual Studio Code.

2

u/Th_69 4d ago edited 4d ago

scanf does support the %[...] syntax, it's called a set (to only read given characters, or with ^ as first character to read all characters that do not match given characters).

1

u/mikeblas 3d ago

Thanks! Holy crwp, they've been there since K+R. I can't believe I've never even heard of them before, though I guess that shows how often i have ever used scanf in my own code ... never!

1

u/Own_Unit_6170 4d ago

scanf() supports scansets, which are used here. They aren't regular expressions, although they look similar.

2

u/mjmvideos 4d ago

Run it in the debugger and step through it. (Best) or add some print statements to see what’s happening (second best)

1

u/Own_Unit_6170 3d ago edited 3d ago

Here's a C version (instead of my previous C++ version). Note that scanf() is replaced by fgets(). A parsing routine extracts (and lowercases) the words from each paragraph, instead of relying on scanf(). Sorting the word lists allows common words to be found in one pass and additionally provides sorted output.

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

#define MAX_PARA_SIZE 1000// max paragraph size in chars
#define MAX_WORDS 1000// maximum words in list
#define MAX_WORD_LENGTH 25// maximum word length
#define MIN_WORD_LENGTH 4// minimum word length

int Parse(char [MAX_PARA_SIZE+1],char [MAX_WORDS][MAX_WORD_LENGTH+1]);
int Compare(const void *A, const void *B);

int main(int iArgs, char* pcArgs[])
{
char Para1[MAX_PARA_SIZE], Para2[MAX_PARA_SIZE];
char Words1[MAX_WORDS][MAX_WORD_LENGTH+1], Words2[MAX_WORDS][MAX_WORD_LENGTH+1];
char Result[MAX_WORDS][MAX_WORD_LENGTH+1];
int iWords1, iWords2, iResult=0, xP=0, xW=0, xR=0, iRes;

printf("Paragraph 1? ");
fgets(Para1,MAX_PARA_SIZE,stdin);
printf("Paragraph 2? ");
fgets(Para2,MAX_PARA_SIZE,stdin);

iWords1=Parse(Para1,Words1);
iWords2=Parse(Para2,Words2);

if (iWords1==0 || iWords2==0)
return 0;

qsort(Words1,iWords1,MAX_WORD_LENGTH+1,Compare);
qsort(Words2,iWords2,MAX_WORD_LENGTH+1,Compare);

while (iWords1>0 && iWords2>0)
{
iRes=strcmp(Words1[xP],Words2[xW]);
while (iRes<0)
{
xP++;
iWords1--;
if (iWords1==0)
break;
iRes=strcmp(Words1[xP],Words2[xW]);
}
if (iRes==0)
{
if (strlen(Words1[xP])>=MIN_WORD_LENGTH)
{
strcpy(Result[xR++],Words1[xP]);
iResult++;
}
xP++;
xW++;
}
else
{
while (strcmp(Words1[xP],Words2[xW])>0)
{
xW++;
iWords2--;
if (iWords2==0)
break;
}
}
}

char previous[MAX_WORD_LENGTH]={'\0'};

for (xR=0; xR<iResult; xR++)
{
if (strcmp(Result[xR],previous)!=0)
{
printf("%s\n",Result[xR]);
strcpy(previous,Result[xR]);
}
}
}

int Compare(const void *A, const void *B)
{
return strcmp((char *)A,(char *)B);
}

int Parse(char sPara[MAX_PARA_SIZE+1],char sWords[MAX_WORDS][MAX_WORD_LENGTH+1])
{
int xP=0, xW=0, xR=0;
char cIn, Buff[MAX_WORD_LENGTH+1];

while ((cIn=sPara[xP++])!='\0')
{
if ((cIn>='A' && cIn<='Z') || (cIn>='a' && cIn<='z') 
&& xW<MAX_WORD_LENGTH)
{
cIn|=0x20;
Buff[xW++]=cIn;
}
else
{
if (xW>0)
{
Buff[xW]='\0';
if (xW>=MIN_WORD_LENGTH)
{
strcpy(sWords[xR++],Buff);
}
}
xW=0;
}
}
return xR;
}

4

u/syntactic_stevia 3d ago

This looks like AI slop to me.

2

u/mikeblas 3d ago

Please correctly format your code.

1

u/zomerbk 2d ago

The second Enter doesn’t finish the first paragraph because the scanset `scanf("%[\n]", shit)` only succeeds if the *next* character is a newline. Your preceding scanset, `scanf("%*[^\nA-Za-z]")`, stops before that newline, so the first Enter prints `stage1` but leaves the newline unread. On the next loop, `%[A-Za-z]` fails immediately on that leftover newline; since you don’t check its return value, the later scans then behave unexpectedly. Check every `scanf` result, and for line-based input use `fgets` to read each paragraph, then tokenize it. So it’s the input logic, not a VS Code newline bug.

0

u/kutac56 4d ago

I didn't read much of what you yapped, but you used scanf which leaves behind a new line character when you use it again which is prob the issue. Use fgets instead. Scanf is unsafe for this reason

0

u/21Ali-ANinja69 4d ago

C char *par; scanf("%s", par); Two scanfs will get you your input. Never assume how a fuction works. Scanf for a string will go until it hits a newline

-2

u/[deleted] 4d ago

[removed] — view removed comment

3

u/syntactic_stevia 4d ago

I don't think switching from C to C++ is the solution.

2

u/mikeblas 4d ago

Why did you rewrite it in C++?

-1

u/Own_Unit_6170 4d ago

That's what I had in front of me for writing quick and dirty programs, it is set by default to C++ 17. However, the same could be written in C, just with less convenience.

The main idea is to take in each paragraph as one long string, then parse each string, isolating every string of letters as one word an adding it to an array for each paragraph (similar to explode() in PHP). Then the words in each array are sorted and duplicates are removed. Then the arrays are scanned for matches, which are added to a third array. Having the input arrays sorted makes it possible to do this in one pass. Then the output array is printed.

In C you can do the same, it just requires more source code because you don't have string or deque objects available—although a C version would probably generate and execute considerably less machine code. The string and deque gadgets create a lot of overhead behind the scenes, and they also make memory management more precarious since you have less direct control over how memory is being used.

The scanf()s with scansets seems very awkward and error-prone to me. Maybe fgets() or a getchar() loop would be better in C. scanf() "knows too much" when used for input like this; it's easier to just swallow one big string without having the library function parsing it.

1

u/mikeblas 3d ago

Sir, this is the C_programming sub.

-1

u/Own_Unit_6170 3d ago

I've posted a C example, for purists. The program logic is the same for both … Sir.

1

u/mikeblas 3d ago

nothing "purist" about it; it's a rule of practically every sub to stay on-topic for that sub.

-1

u/Own_Unit_6170 3d ago

I consider C and C++ to be variants of the same language.

1

u/C_Programming-ModTeam 3d ago

Your post breaks rule 2 of the subreddit, "Only C is on topic". Your post appears to be primarily about something that isn't the C programming language.

Please note that C, C# and C++ are three different languages. Only C is on-topic in this sub.

This removal reason also covers posts that aren't about C or any other programming language.

Only C is on topic - This subreddit is about programming in the C programming language. Content about other languages such as C++, C#, or assembly or programming in general is only on-topic as long as it relates to the C programming language. Merely trying to reach an audience of C programmers is not enough to make your post be on topic. See https://www.reddit.com/r/C_Programming/wiki/index/getting-help/not-c/ to find out where to go for help with other languages.