Programozás‎ > ‎

Számok beolvasása

Ha billentyűzetről kérünk be számokat, akkor a háttérben a begépelt (szöveges) információt át kell alakítani a gépi számábrázolásnak megfelelően. Például ha a felhasználó a "137" karaktersorozatot gépeli be, akkor alapból három karakterünk van: "1", "3" és "7". Ebből kell létrehoznunk a választott számtípusnak megfelelő kódot, például egy 32-bites előjeles egész számot.
Hasonló a helyzet, ha a bemenetet egy olyan "szöveges" állományból olvassuk be, ahol az információ emberi fogyasztásra alkalmasan, tehát karakteresen van megadva.

Ezeket az átalakításokat a programozási nyelv, vagy a hozzá kapcsolódó könyvtári csomagok eljárásai végzik. Mivel ez az egyik leginkább nyelv-specifikus része a programozásnak, az alábbiakban konkrét kódokat adunk meg.



Számok beolvasása konzolról (=billentyűzet / standard bemenet)

Pascal

A pascal nyelv nagyon kényelmes szolgáltatásokat nyújt a bemenet feldolgozásához. Tetszőleges számú, szóközökkel elválasztott értéket tud beolvasni egy bemeneti sorból, és elvégzi a megfelelő típus-konverziókat is.

program beolvas;
var
    a, b : integer;
    c : longint;
    d : real;
begin
    readln(a,b,c,d);
    writeln(a,' ',b,' ',c,' ',d);
end.

A fenti program helyesen működik az alábbi bemenetre:

    137  -2000 1234567 3.14

Java

Java nyelvben picit bonyolultabb a helyzet, mert a bemenet olvasása során felmerülhetnek hibák (kivételek), melyeket a nyelv szigorú szabályai miatt le kell kezelni.

1. változat
Jelezzük a nem kezelt kivételt.

import java.io.*;

public class szamok {
   
    public static void main (String args[]) throws IOException {
        BufferedReader be = new BufferedReader(new InputStreamReader(System.in));
        int a = Integer.parseInt(be.readLine());
        int b = Integer.parseInt(be.readLine());
        System.out.println("a+b= "+(a+b));
    }
}

2. változat
Használjuk az "intelligens" Scanner osztályt.

import java.util.Scanner;

public class szamok {
   
    public static void main (String args[]) {
        Scanner  be = new Scanner(System.in);
        int a = be.nextInt();
        int b = be.nextInt();
        System.out.println("a+b= "+(a+b));
    }
}

1. Vigyázat! A Scanner feldolgozza a teljes bemenetet. Ha az első sorban (az első enter előtt) több egész számot is megadunk, akkor az első kettő kerül az a és b változóba, a többit átugorja a beolvasás.

2. Vigyázat! A Scanner lokalizált módon olvassa be a lebegőpontos számokat. Ha magyar nyelvű operációs rendszerrel dolgozunk, akkor tizedes elválasztónak a vessző számít(ana) és nem a pont. A szokás viszont az, hogy a bemenetekben az amerikai jelölést használják. Erre figyelmeztetnünk kell a programot:


import java.util.Scanner;
import java.util.Locale;

public class szamok {
    
    public static void main (String args[]) {
        Scanner  be = new Scanner(System.in);
        be.setLocale(Locale.US);
        double a = be.nextDouble();
        double b = be.nextDouble();
        System.out.println("a+b= "+(a+b));
    }
}



C
C++
C#

Számok beolvasása szöveges állományból

Példa egy lehetséges bemenetre

A példa kedvéért egy olyan bemenettel fogunk dolgozni, amely térbeli pontok koordinátáit tárolja. Az első sor a pontok számát adja meg (feltesszük, hogy legfeljebb 1000 pont lehet), majd soronként három egész koordináta következik, szóközökkel elválasztva. A koordináták nem negatívak, és egyik sem nagyobb, mint 10000. A példaprogramok teljessége érdekében két dolgot fogunk az adatokkal csinálni:
  • tömbbe olvassuk őket, mert egy bonyolultabb algoritmusnál szükség lehet arra, hogy a bemenet teljes egészében a memóriában legyen;
  • kiírjuk őket a képernyőre, hogy ellenőrizni tudjuk a beolvasás helyességét.
A bemeneti állomány neve: bemenet.txt.

Pascal

program Bemenet;
var
    N,i : integer;
    T : array[1..1000,1..3] of integer;
    F : text;
begin
    assign(F,'bemenet.txt');
    reset(F);
    readln(F,N);
    for i := 1 to N do begin
        readln(F,T[i,1],T[i,2],T[i,3]);
        writeln(T[i,1],' ',T[i,2],' ',T[i,3]);
    end;
    close(F);
end.


Megjegyzések:
  • A Pascal nyelv readln utasítása kezelni tudja a bemeneti sorban az adatokat elválasztó szóközöket.
  • A fenti program nem érzékeny arra, ha a sorok végén további adatok is vannak a harmadik szám után.
  • Pascalban fordítási időben kell megadni a tömbök méretét, ezért a feladat specifikációjából ki kell derülnie, hogy mekkora lehet a legnagyobb lehetséges bemenet, és erre kell méretezni a tömböt.
  • Az inputot soronként olvassuk, ezért van jelentősége a sorvége karakterek helyes kezelésének.
  • A szöveg -> szám átalakítást a readln utasítás végzi.

Java

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;

public class bemenet {
    
    public static void main (String args[]) throws FileNotFoundException, IOException 
    {
        BufferedReader BE = new BufferedReader(new FileReader("bemenet.txt"));
        String sor = BE.readLine();
        int N = Integer.parseInt(sor);
        int[][] T = new int[N][3];
        for(int i = 0; i < N; i++){
            sor = BE.readLine();
            String[] nums = sor.split(" ");
            for(int j = 0; j < 3; j++){
                T[i][j] = Integer.parseInt(nums[j]);                
            }
            System.out.println(T[i][0]+" "+T[i][1]+" "+T[i][2]+" ");
        }
        BE.close();
    }
}

Megjegyzések:
  • Java-ban a tömböket 0-tól indexeljük
  • a sor.split(" ") dinamikusan hozza létre a szóköz mentén feldarabolt karakterlácból a karakterláncok tömbjét, azért nem kell előre tudnia, hogy hány részre esik szét egy sor
  • Az inputot soronként olvassuk, ezért van jelentősége a sorvége karakterek helyes kezelésének.
  • A szöveg -> szám átalakítást az Integer.parseInt() függvény végzi.
A Scanner objektum használata picit tömörebb kódot eredményez:

import java.io.FileReader;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class bemenet {
    
    public static void main (String args[]) throws FileNotFoundException
    {
        Scanner BE = new Scanner(new FileReader("bemenet.txt"));        
        int N = BE.nextInt();
        int[][] T = new int[N][3];
        for(int i = 0; i < N; i++){            
            for(int j = 0; j < 3; j++){
                T[i][j] = BE.nextInt();                
            }
            System.out.println(T[i][0]+" "+T[i][1]+" "+T[i][2]+" ");
        }
        BE.close();
    }
}

C

#include "stdio.h"    

int main()
{
    int N,i;
    FILE* BE = fopen("bemenet.txt", "r");
    fscanf(BE, "%d", &N);

    int T[1000][3];
    for(i=0; i<N; i++)
    {               
        fscanf(BE, "%d %d %d", &T[i][0], &T[i][1], &T[i][2]);       
        printf("%d %d %d\n", T[i][0], T[i][1], T[i][2]);      
    }

    fclose(BE);
    return 0;
}

Megjegyzések:

  • A fscanf függvény a sorvégéket is "fehér szóközként" (whitespace) kezeli, ezért a sortörések nem számítanak, de ha valamelyik sorban nem passzol a számok darabszáma, akkor onnantól az egész beolvasás elcsúszik.
  • A szöveg -> szám átalakítást az fscanf függvény végzi.

C++

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    int N,i;
   
    ifstream BE("bemenet.txt");
    BE >> N;
    int T[N][3];
   
    for (i = 0; i< N; i++){
        BE >> T[i][0];
        BE >> T[i][1];
        BE >> T[i][2];
        cout <<T[i][0]<<" "<<T[i][1]<<" "<<T[i][2]<<"\n";
    }
    BE.close();
    return 0;
}

Megjegyzések:
  • A  << operátor a sorvégéket is "fehér szóközként" (whitespace) kezeli, ezért a sortörések nem számítanak, de ha valamelyik sorban nem passzol a számok darabszáma, akkor onnantól az egész beolvasás elcsúszik.
  • A szöveg -> szám átalakítást a << operátor végzi. (Implicit típuskonverzió.)

Lebegőpontos számok beolvasása Java-ban

A lebegőpontos számok olvasásakor találkozhatunk a lokalizáció problémájával. Magyarországon vesszővel választjuk el a szám törtrészét az egész részétől, míg a világ sok országában a tizedespontot használják. Az informatika területén előfordulhat, hogy a lebegőpontos adatok - az adott ország nyelvtani szabályaitól függetlenül - tizedesponttal vannak kódolva. A Java nyelv viszont (alapértelmezés szerint) a telepítés lokalizációja alapján olvasná a törteket, ezért explicit meg kell adni az adatok formátumát.

Legyen az adatok.txt valami ilyen:

10.2
123.1
15.867
33.567


A beolvasást így végezhetjük:

import java.io.*;
import java.util.Scanner;
import java.util.Locale;

class olvas {
    public static void main(String args[]) throws IOException {
        Scanner be = new Scanner(new FileReader("adatok.txt")).useLocale(Locale.ENGLISH);
        while (be.hasNext()) {
            double d = be.nextDouble();
            System.out.println(d);
        }
        be.close();
    }
}