7 svar
207 visningar
InteDenSmartaste 41
Postad: 1 sep 2023 21:59

Hur läser jag in en string som flera ord?

Tja! Denna fråga kom på mitt prov som jag är ganska säker på att jag kuggade. Jag har inte så stor erfarenhet när det kommer till programmering, men det här var vad jag försökte göra:

- läsa in flera ord som en sträng

- läsa igenom strängen bokstav för bokstav

- bokstäverna lagras i en 2D matris med dimensionerna [antal ord][antal bokstäver]

- om en bokstav är "mellanslag" så ökar antal ord med 1, tanken är då att en ny rad ska skapas i min matris, dvs ett nytt ord.

När jag försöker debugga med lite printfs ser man dessvärre att jag bara lyckats lagra ett ord... (programmet avslutas efter att ha printat index 1: ). Var brister min logik? Vad gör jag för fel?

Fermatrix 7841 – Fd. Medlem
Postad: 1 sep 2023 22:08 Redigerad: 1 sep 2023 22:12

Använd fgets istället om du vill läsa in hela raden. 

Du kan göra något i denna stilen:

int main()
{
    char buffer[100];
    (void) fgets(buffer, sizeof(buffer), stdin);
    printf("%s", buffer);

    return 0;
}

Vill du vara extra flitig så kan du kika på vad fgets retunerar och ta han om fallet då fgets går sönder. :)

Vill du sedan ha varje ord så kan du använda strtok_s på (" "), så kan du ta de ord för ord. Men det går att lösa det på många sätt.

InteDenSmartaste 41
Postad: 1 sep 2023 22:36

Hej! Jag har testat fgets också, men utifrån vad jag kan se ger den exakt samma sak? Efter provet googlade jag lite på lösningar och då kom strtok funktionen upp, men den har aldrig nämnts under kursens gång så jag tror inte det är den metod som vi önskats använda. 

De lär lägga upp facit snart och då får jag väl se hur uppgiften borde lösas, men jag vill lära mig av mina misstag och förstå varför mitt tillvägagångssätt är ett sånt misslyckande? Är det en omöjlig approach att läsa in det som en 2D array? (skickar med koden för bilden blev ganska suddig)

#include <stdio.h>
#include <string.h>
#define LETTERS_MAX 30 + 1
#define WORDS_MAX 20

void getWords();

int main(void) {
getWords();
}

void getWords() {
char input[LETTERS_MAX] = {0};
char words[WORDS_MAX][LETTERS_MAX] = {0};
int wordNb = 0;
printf("Ange ord avsluta med *: ");
fgets(input, sizeof(input), stdin);

for (int c = 0; c < LETTERS_MAX; c++) {
if (input[c] == ' ') {
wordNb++;
} else {
words[wordNb][c] = input[c];
}
}

printf("Detta finns lagrat i min matris: \n");
for (int r = 0; r < wordNb; r++) {
printf("index %d: %s\n", r, words[r]);
}
}

anders_k 237
Postad: 2 sep 2023 11:08 Redigerad: 2 sep 2023 11:09

 

Normalt hade man löst det med fgets och sen strtok för att plocka ut orden.

Men från frågan så verkar det som man vill att du skall läsa in orden medan användaren matar in dem.

Detta kan man göra genom att läsa tecken för tecken från tangentbordet

t.ex.

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


int main()
{
  char ch;
  int maxantalord = 100;
  char ord[200] = { 0 };
  char** ordlista = malloc(sizeof(char*)*maxantalord);
  int antalord = 0;
  int tecken = 0;

  do
  {
    ch = fgetc(stdin);
    switch (ch)
    {
    case ' ': // ordslut, ignorera multipla mellanslag
    case '*':
      if (tecken > 0) 
      {
        ord[tecken] = 0;
        ordlista[antalord++] = strdup(ord);
        tecken = 0;
      }
      break;
    default:
      ord[tecken++] = ch;
      break;
    }
    // TODO: använd realloc  ifall antal ord överstiger maxantalord
  }
  while (ch != '*'); // avsluta med *
  
  for (int i = 0; i < antalord; ++i) 
  {
    printf("%s ", ordlista[i]);
    free(ordlista[i]);
  }
  free(ordlista);
  return 0;
}
InteDenSmartaste 41
Postad: 3 sep 2023 00:35

Sorry känns fortfarande lite för avancerat, känner varken till malloc, strdup, eller free. Detta var bara en 10-15 föreläsningar lång grundkurs/intro till programmering så vi har inte riktigt gått igenom så många funktioner. Men tack så mycket för hjälpen i alla fall!

Fermatrix 7841 – Fd. Medlem
Postad: 3 sep 2023 00:38

Var det en hemuppgift? Känns ändå som en ganska dryg uppgift att göra på 30 min på penna och papper.

InteDenSmartaste 41
Postad: 3 sep 2023 01:14

Nä, det var en riktigt tenta. 5 frågor på 5 timmar, på dator men inget internet. Detta var fråga 2, men eftersom jag inte samlat ihop tillräckligt många poäng så lär de inte kolla på resten av provet. ;/

anders_k 237
Postad: 9 sep 2023 18:18 Redigerad: 9 sep 2023 18:20

 

Ja du skulle kunna sköta det hela med en 2-dim matris som
du gjorde

Det är bättre att använda fgets att läsa från tangentbordet
då får alla tecken inklusive \n på slutet.

if (fgets(input, LETTERS_MAX, stdin)== NULL)
{
  return -1;
}

Som du har det i din bild läser du upp till LETTERS_MAX
men du kollar inte hur många tecken som du läste in, du kan
kontrollera det med strlen(input).

För att hålla reda på hur många tecken du skall kopiera ha en start variabel, den står alltid på första bokstaven i ett ord.

int start = 0;
for (int c = 0; c < strlen(input); ++c)
{
  (* använd isspace() istället för input[c]==' ' 
     isspace(c) returnerar != 0 om input[c] == ' ' 
     eller input[c] == '\n'vilket är praktiskt 
     eftersom fgets() returnerar \n som sista 
     tecknet i input. 
   *)
   if (isspace(input[c]))
   {
     (* för att kopiera ordet från input till matrisen
        måste du kopiera tecknen från start till c
        detta kan du göra på flera sätt här som en 
        enkel loop
      *)
      for (int i = 0; i < c - start; ++i)
      { 
        words[wordNb][i] = input[i + start];
      }
      words[wordNb][i] = '\0'; (* avsluta strängen *)
      ++wordNb; (* ny start, hoppa över ' ' *)
      start = c + 1;
   }
}

Och så här ser det ut utan kommentarer

 

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define LETTERS_MAX 31
#define MAXWORDS 20

int main()
{
  char words[MAXWORDS][LETTERS_MAX] = {};
  int wordNb = 0;
  char input[LETTERS_MAX]={};
  
  if (fgets(input,sizeof(input),stdin) == NULL)
   return -1;

  int start = 0;
  for (int c = 0; c < strlen(input); ++c)
  {
    if (isspace(input[c]))
    {
      int i;
      for (i = 0; i < c - start; ++i)
      { 
        words[wordNb][i] = input[i + start];
      }
      words[wordNb][i] = '\0'; 
      ++wordNb; 
      start = c + 1;
    }
   }

   for (int i = 0; i < wordNb; ++i)
     puts(words[i]);
}

Om du inte vill använda strlen kan du enkelt göra en sån funktion som räknar tecken fram tills '\0'

Svara
Close