Toutes les personnes. Je suis désolé pour mon mauvais anglais. J'ai une tâche assez simple: lire un fichier char par char et compter chaque lettre. La langue n'a pas d'importance. Au début, j'ai utilisé une chaîne avec tous les caractères restreints:

"1234567890`~!@#$%^&*()_+-=!№;%:?*(){}[];:|',./<>?  "    

C'était une idée stupide, alors j'ai décidé d'utiliser:

!Char.IsLetter(data[i].letter)
data.RemoveAt(i);

Ça n'a pas marché. Même ce qui suit n'a pas fonctionné (enfin, je ne m'y attendais pas)

                if(Char.IsDigit(data[i].letter) || Char.IsSymbol(data[i].letter)||Char.IsControl(data[i].letter) ||Char.IsNumber(data[i].letter) ||Char.IsPunctuation(data[i].letter) ||Char.IsSeparator(data[i].letter) ||Char.IsSymbol(data[i].letter) ||Char.IsWhiteSpace(data[i].letter))
                data.RemoveAt(i);

Il laisse encore passer certains nombres et sybols. Le plus ennuyeux est «\ r», dont je ne peux pas me débarrasser. J'ai besoin d'une solution qui puisse dire si un caractère est une lettre. Je suis novice, donc plus simple signifie mieux. Merci d'avance!

1
TigerMax96 28 déc. 2015 à 22:32

4 réponses

Meilleure réponse

Si votre data est en fait un List<Data>(), et si votre code ressemble à ceci:

        for (int i = 0; i < data.Count; i++)
            if (!Char.IsLetter(data[i].letter))
                data.RemoveAt(i);

En utilisant

public class Data
{
    public char letter { get; set; }
}

Ensuite, vous avez un bogue - vous sauterez le test pour chaque lettre suivant une lettre supprimée, car l'appel à RemoveAtt(i) réduira l'index de toutes les entrées de liste suivantes de 1. À la place, vous devriez utiliser RemoveAll():

        data.RemoveAll(d => !char.IsLetter(d.letter));
1
dbc 28 déc. 2015 à 20:09

Pour obtenir simplement un compte des lettres dans le tableau d'objets:

data.Count(x => char.IsLetter(x.letter));

Cela utilise la méthode LINQ Count et appelle char.IsLetter pour le champ letter pour déterminer si chaque caractère doit être ajouté au compte.

Exemple: (avec juste une chaîne et non un tableau d'objets)

var data = "ABC_123_\r_%$#";
var count = data.Count(char.IsLetter);
Console.WriteLine(count);

Imprime 3 comme prévu.

Notez que vous devez ajouter: using System.Linq; en haut de votre fichier s'il n'y est pas déjà.

4
Cyral 28 déc. 2015 à 19:40

Votre problème est que vous modifiez la collection pendant l'itération

using System.Collections.Generic;
using System.Linq;

namespace Example
{
  class Program
  {
    static void Main(string[] args)
    {
        List<char> data =  "1234567890".ToList();
        //This does not remove all the element!!!
        for (int i = 0; i < data.Count; i++)
            data.RemoveAt(i);
    }
  }
}

Tu en as besoin

static void Main(string[] args)
{
        List<char> data = "1234567890".ToList();

        List<char> toDelete = new List<char>();

         for (int i = 0; i < data.Count; i++)
            toDelete.Add(data[i]);

        for (int i = 0; i < toDelete.Count; i++)
            data.Remove(toDelete[i]);
}

Ou avec moins de lignes (comme vous le voyez, IsLetter fonctionne bien, il n'y a pas de problème avec \ r \ n)

 List<char> data = (Environment.NewLine + "1234567890").ToList();
 data = data.Where(l => char.IsLetter(l)).ToList();
1
George Vovos 28 déc. 2015 à 20:08

Utilisez plutôt une expression régulière

Regex.IsMatch(input, @"^[a-zA-Z]+$");

Ou plus simple

Regex.IsMatch(input, "[a-zA-Z]");
0
STORM 28 déc. 2015 à 19:36