Hoe staat u toe dat spaties worden ingevoerd met scanf?

Met de volgende code:

char *name = malloc(sizeof(char) + 256); 
printf("What is your name? ");
scanf("%s", name);
printf("Hello %s. Nice to meet you.\n", name);

Een gebruiker kan zijn naam invoeren, maar wanneer hij een naam invoert met een spatie zoals Lucas Aardvark, snijdt scanf()gewoon alles af na Lucas. Hoe laat ik scanf()spaties toestaan


Antwoord 1, autoriteit 100%

Mensen (en vooralbeginners) mogen nooit scanf("%s")of gets()of andere functies gebruiken die dat wel doen. geen bufferoverloopbeveiliging hebben, tenzij u zeker weet dat de invoer altijd een bepaald formaat zal hebben (en misschien zelfs dan niet).

Onthoud dat scanfstaat voor “scan formatted” en dat er weinig minderis geformatteerd dan door de gebruiker ingevoerde gegevens. Het is ideaal als u volledige controle heeft over het invoergegevensformaat, maar over het algemeen niet geschikt is voor gebruikersinvoer.

Gebruik fgets()(die heeftbescherming tegen bufferoverloop) om uw invoer in een string te krijgen en sscanf()om het te evalueren. Omdat je gewoon wilt wat de gebruiker heeft ingevoerd zonder te ontleden, heb je in dit geval toch niet echt sscanf()nodig:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Maximum name size + 1. */
#define MAX_NAME_SZ 256
int main(int argC, char *argV[]) {
    /* Allocate memory and check if okay. */
    char *name = malloc(MAX_NAME_SZ);
    if (name == NULL) {
        printf("No memory\n");
        return 1;
    }
    /* Ask user for name. */
    printf("What is your name? ");
    /* Get the name, with size limit. */
    fgets(name, MAX_NAME_SZ, stdin);
    /* Remove trailing newline, if there. */
    if ((strlen(name) > 0) && (name[strlen (name) - 1] == '\n'))
        name[strlen (name) - 1] = '\0';
    /* Say hello. */
    printf("Hello %s. Nice to meet you.\n", name);
    /* Free memory and exit. */
    free (name);
    return 0;
}

Antwoord 2, autoriteit 63%

Probeer

char str[11];
scanf("%10[0-9a-zA-Z ]", str);

Ik hoop dat dat helpt.


Antwoord 3, autoriteit 28%

Dit voorbeeld gebruikt een omgekeerde scanset, dus scanf blijft waarden opnemen totdat het een ‘\n’– nieuwe regel tegenkomt, dus ook spaties worden opgeslagen

#include <stdio.h>
int main (int argc, char const *argv[])
{
    char name[20];
    // get up to buffer size - 1 characters (to account for NULL terminator)
    scanf("%19[^\n]", name);
    printf("%s\n", name);
    return 0;
}

Antwoord 4, autoriteit 12%

U kunt dit gebruiken

char name[20];
scanf("%20[^\n]", name);

Of dit

void getText(char *message, char *variable, int size){
    printf("\n %s: ", message);
    fgets(variable, sizeof(char) * size, stdin);
    sscanf(variable, "%[^\n]", variable);
}
char name[20];
getText("Your name", name, 20);

DEMO


Antwoord 5, autoriteit 4%

Gebruik scanf()niet om strings te lezen zonder een veldbreedte op te geven. U moet ook de retourwaarden controleren op fouten:

#include <stdio.h>
#define NAME_MAX    80
#define NAME_MAX_S "80"
int main(void)
{
    static char name[NAME_MAX + 1]; // + 1 because of null
    if(scanf("%" NAME_MAX_S "[^\n]", name) != 1)
    {
        fputs("io error or premature end of line\n", stderr);
        return 1;
    }
    printf("Hello %s. Nice to meet you.\n", name);
}

U kunt ook fgets()gebruiken:

#include <stdio.h>
#define NAME_MAX 80
int main(void)
{
    static char name[NAME_MAX + 2]; // + 2 because of newline and null
    if(!fgets(name, sizeof(name), stdin))
    {
        fputs("io error\n", stderr);
        return 1;
    }
    // don't print newline
    printf("Hello %.*s. Nice to meet you.\n", strlen(name) - 1, name);
}

Antwoord 6, autoriteit 3%

U kunt de functie fgets()gebruiken om een tekenreeks te lezen of scanf("%[^\n]s",name);gebruiken zodat het lezen van tekenreeksen beëindigen bij het tegenkomen van een teken van een nieuwe regel.


Antwoord 7, autoriteit 2%

getline()

Nu onderdeel van POSIX, niettemin.

Het lost ook het buffertoewijzingsprobleem op waar u eerder naar vroeg, hoewel u ervoor moet zorgen dat het geheugen freewordt.


Antwoord 8

Als iemand nog steeds op zoek is, dit is wat voor mij werkte: een willekeurige lengte van een tekenreeks lezen, inclusief spaties.

Dank aan vele posters op internet voor het delen van deze eenvoudige & elegante oplossing.
Als het werkt, gaat het krediet naar hen, maar eventuele fouten zijn van mij.

char *name;
scanf ("%m[^\n]s",&name);
printf ("%s\n",name);

Antwoord 9

U kunt scanfgebruiken voor dit doel met een beetje truc. Eigenlijk moet u gebruikersinvoer toestaan ​​totdat de gebruiker treft (\n) invoeren. Dit beschouwt elk karakter, inclusief Space . Hier is voorbeeld:

int main()
{
  char string[100], c;
  int i;
  printf("Enter the string: ");
  scanf("%s", string);
  i = strlen(string);      // length of user input till first space
  do
  {
    scanf("%c", &c);
    string[i++] = c;       // reading characters after first space (including it)
  } while (c != '\n');     // until user hits Enter
  string[i - 1] = 0;       // string terminating
return 0;
}

Hoe werkt dit? Wanneer de gebruiker tekens van standaardinvoer invoert, worden ze opgeslagen in string variabele tot de eerste lege ruimte. Daarna blijft de rest van de invoer in de invoerstroom en wacht op het volgende scanf. Vervolgens hebben we een forlus die Char per Char van Input Stream (tot \n) neemt en maakt hen aan het einde van string variabele, Dus het vormen van een complete snaar hetzelfde als gebruikersinvoer van toetsenbord.

Ik hoop dat dit iemand zal helpen!


Antwoord 10

Terwijl u echt niet scanf()voor dit soort dingen mag gebruiken, omdat er veel betere oproepen zijn, zoals gets()of getline(), het kan worden gedaan:

#include <stdio.h>
char* scan_line(char* buffer, int buffer_size);
char* scan_line(char* buffer, int buffer_size) {
   char* p = buffer;
   int count = 0;
   do {
       char c;
       scanf("%c", &c); // scan a single character
       // break on end of line, string terminating NUL, or end of file
       if (c == '\r' || c == '\n' || c == 0 || c == EOF) {
           *p = 0;
           break;
       }
       *p++ = c; // add the valid character into the buffer
   } while (count < buffer_size - 1);  // don't overrun the buffer
   // ensure the string is null terminated
   buffer[buffer_size - 1] = 0;
   return buffer;
}
#define MAX_SCAN_LENGTH 1024
int main()
{
   char s[MAX_SCAN_LENGTH];
   printf("Enter a string: ");
   scan_line(s, MAX_SCAN_LENGTH);
   printf("got: \"%s\"\n\n", s);
   return 0;
}

Antwoord 11

/*reading string which contains spaces*/
#include<stdio.h>
int main()
{
   char *c,*p;
   scanf("%[^\n]s",c);
   p=c;                /*since after reading then pointer points to another 
                       location iam using a second pointer to store the base 
                       address*/ 
   printf("%s",p);
   return 0;
 }

Other episodes